blob: 3904d86be71535104e14a3fa05aa66d8addedbe7 [file] [log] [blame]
Chris Lattner77cd2a02007-10-11 00:43:27 +00001//===--- RewriteTest.cpp - Playground for the code rewriter ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Hacks and fun related to the code rewriter.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ASTConsumers.h"
Chris Lattner8a12c272007-10-11 18:38:32 +000015#include "clang/Rewrite/Rewriter.h"
Chris Lattner77cd2a02007-10-11 00:43:27 +000016#include "clang/AST/AST.h"
17#include "clang/AST/ASTConsumer.h"
Chris Lattner8a12c272007-10-11 18:38:32 +000018#include "clang/Basic/SourceManager.h"
Steve Naroffebf2b562007-10-23 23:50:29 +000019#include "clang/Basic/IdentifierTable.h"
Chris Lattner77cd2a02007-10-11 00:43:27 +000020using namespace clang;
21
Chris Lattner77cd2a02007-10-11 00:43:27 +000022namespace {
Chris Lattner8a12c272007-10-11 18:38:32 +000023 class RewriteTest : public ASTConsumer {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000024 Rewriter Rewrite;
Chris Lattner01c57482007-10-17 22:35:30 +000025 ASTContext *Context;
Chris Lattner77cd2a02007-10-11 00:43:27 +000026 SourceManager *SM;
Chris Lattner8a12c272007-10-11 18:38:32 +000027 unsigned MainFileID;
Chris Lattner2c64b7b2007-10-16 21:07:07 +000028 SourceLocation LastIncLoc;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000029 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
30 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Steve Naroffebf2b562007-10-23 23:50:29 +000031
32 FunctionDecl *MsgSendFunctionDecl;
33 FunctionDecl *GetClassFunctionDecl;
34
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000035 static const int OBJC_ABI_VERSION =7 ;
Chris Lattner77cd2a02007-10-11 00:43:27 +000036 public:
Chris Lattner01c57482007-10-17 22:35:30 +000037 void Initialize(ASTContext &context, unsigned mainFileID) {
38 Context = &context;
39 SM = &Context->SourceMgr;
Chris Lattner8a12c272007-10-11 18:38:32 +000040 MainFileID = mainFileID;
Steve Naroffebf2b562007-10-23 23:50:29 +000041 MsgSendFunctionDecl = 0;
Steve Naroffc0006092007-10-24 01:09:48 +000042 GetClassFunctionDecl = 0;
Chris Lattner01c57482007-10-17 22:35:30 +000043 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattner77cd2a02007-10-11 00:43:27 +000044 }
Chris Lattner8a12c272007-10-11 18:38:32 +000045
Chris Lattnerf04da132007-10-24 17:06:59 +000046 // Top Level Driver code.
47 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner2c64b7b2007-10-16 21:07:07 +000048 void HandleDeclInMainFile(Decl *D);
Chris Lattnerf04da132007-10-24 17:06:59 +000049 ~RewriteTest();
50
51 // Syntactic Rewriting.
Chris Lattner2c64b7b2007-10-16 21:07:07 +000052 void RewriteInclude(SourceLocation Loc);
Chris Lattnerf04da132007-10-24 17:06:59 +000053 void RewriteTabs();
54 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Chris Lattner311ff022007-10-16 22:36:42 +000055
Chris Lattnerf04da132007-10-24 17:06:59 +000056 // Expression Rewriting.
Chris Lattnere64b7772007-10-24 16:57:36 +000057 Stmt *RewriteFunctionBody(Stmt *S);
58 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
59 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Chris Lattnerf04da132007-10-24 17:06:59 +000060
61 // Metadata emission.
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000062 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl);
63
64 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl);
65
66 void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
67 int NumMethods,
68 const char *prefix,
69 const char *MethodKind,
70 const char *ClassName);
71
72 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
73 int NumProtocols,
74 const char *prefix,
75 const char *ClassName);
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000076 void WriteObjcMetaData();
Chris Lattner77cd2a02007-10-11 00:43:27 +000077 };
78}
79
Chris Lattner8a12c272007-10-11 18:38:32 +000080ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattner77cd2a02007-10-11 00:43:27 +000081
Chris Lattnerf04da132007-10-24 17:06:59 +000082//===----------------------------------------------------------------------===//
83// Top Level Driver Code
84//===----------------------------------------------------------------------===//
85
Chris Lattner8a12c272007-10-11 18:38:32 +000086void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000087 // Two cases: either the decl could be in the main file, or it could be in a
88 // #included file. If the former, rewrite it now. If the later, check to see
89 // if we rewrote the #include/#import.
90 SourceLocation Loc = D->getLocation();
91 Loc = SM->getLogicalLoc(Loc);
92
93 // If this is for a builtin, ignore it.
94 if (Loc.isInvalid()) return;
95
Steve Naroffebf2b562007-10-23 23:50:29 +000096 // Look for built-in declarations that we need to refer during the rewrite.
97 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroffc0006092007-10-24 01:09:48 +000098 if (strcmp(FD->getName(), "objc_msgSend") == 0)
Steve Naroffebf2b562007-10-23 23:50:29 +000099 MsgSendFunctionDecl = FD;
Steve Naroffc0006092007-10-24 01:09:48 +0000100 else if (strcmp(FD->getName(), "objc_getClass") == 0)
Steve Naroffebf2b562007-10-23 23:50:29 +0000101 GetClassFunctionDecl = FD;
102 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000103
104 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000105 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
106 return HandleDeclInMainFile(D);
107
Chris Lattnerf04da132007-10-24 17:06:59 +0000108 // Otherwise, see if there is a #import in the main file that should be
109 // rewritten.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000110 RewriteInclude(Loc);
111}
112
Chris Lattnerf04da132007-10-24 17:06:59 +0000113/// HandleDeclInMainFile - This is called for each top-level decl defined in the
114/// main file of the input.
115void RewriteTest::HandleDeclInMainFile(Decl *D) {
116 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
117 if (Stmt *Body = FD->getBody())
118 FD->setBody(RewriteFunctionBody(Body));
119
120 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
121 ClassImplementation.push_back(CI);
122 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
123 CategoryImplementation.push_back(CI);
124 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
125 RewriteForwardClassDecl(CD);
126 // Nothing yet.
127}
128
129RewriteTest::~RewriteTest() {
130 // Get the top-level buffer that this corresponds to.
131 RewriteTabs();
132
133 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
134 // we are done.
135 if (const RewriteBuffer *RewriteBuf =
136 Rewrite.getRewriteBufferFor(MainFileID)) {
137 printf("Changed:\n");
138 std::string S(RewriteBuf->begin(), RewriteBuf->end());
139 printf("%s\n", S.c_str());
140 } else {
141 printf("No changes\n");
142 }
143
144 // Rewrite Objective-c meta data*
145 WriteObjcMetaData();
146}
147
148//===----------------------------------------------------------------------===//
149// Syntactic (non-AST) Rewriting Code
150//===----------------------------------------------------------------------===//
151
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000152void RewriteTest::RewriteInclude(SourceLocation Loc) {
153 // Rip up the #include stack to the main file.
154 SourceLocation IncLoc = Loc, NextLoc = Loc;
155 do {
156 IncLoc = Loc;
157 Loc = SM->getLogicalLoc(NextLoc);
158 NextLoc = SM->getIncludeLoc(Loc);
159 } while (!NextLoc.isInvalid());
160
161 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
162 // IncLoc indicates the header that was included if it is useful.
163 IncLoc = SM->getLogicalLoc(IncLoc);
164 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
165 Loc == LastIncLoc)
166 return;
167 LastIncLoc = Loc;
168
169 unsigned IncCol = SM->getColumnNumber(Loc);
170 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
171
172 // Replace the #import with #include.
173 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
174}
175
Chris Lattnerf04da132007-10-24 17:06:59 +0000176void RewriteTest::RewriteTabs() {
177 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
178 const char *MainBufStart = MainBuf.first;
179 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000180
Chris Lattnerf04da132007-10-24 17:06:59 +0000181 // Loop over the whole file, looking for tabs.
182 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
183 if (*BufPtr != '\t')
184 continue;
185
186 // Okay, we found a tab. This tab will turn into at least one character,
187 // but it depends on which 'virtual column' it is in. Compute that now.
188 unsigned VCol = 0;
189 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
190 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
191 ++VCol;
192
193 // Okay, now that we know the virtual column, we know how many spaces to
194 // insert. We assume 8-character tab-stops.
195 unsigned Spaces = 8-(VCol & 7);
196
197 // Get the location of the tab.
198 SourceLocation TabLoc =
199 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
200
201 // Rewrite the single tab character into a sequence of spaces.
202 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
203 }
Chris Lattner8a12c272007-10-11 18:38:32 +0000204}
205
206
Chris Lattnerf04da132007-10-24 17:06:59 +0000207void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
208 int numDecls = ClassDecl->getNumForwardDecls();
209 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
210
211 // Get the start location and compute the semi location.
212 SourceLocation startLoc = ClassDecl->getLocation();
213 const char *startBuf = SM->getCharacterData(startLoc);
214 const char *semiPtr = strchr(startBuf, ';');
215
216 // Translate to typedef's that forward reference structs with the same name
217 // as the class. As a convenience, we include the original declaration
218 // as a comment.
219 std::string typedefString;
220 typedefString += "// ";
221 typedefString.append(startBuf, semiPtr-startBuf+1);
222 typedefString += "\n";
223 for (int i = 0; i < numDecls; i++) {
224 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
225 typedefString += "typedef struct ";
226 typedefString += ForwardDecl->getName();
227 typedefString += " ";
228 typedefString += ForwardDecl->getName();
229 typedefString += ";\n";
230 }
231
232 // Replace the @class with typedefs corresponding to the classes.
233 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
234 typedefString.c_str(), typedefString.size());
235}
236
237//===----------------------------------------------------------------------===//
238// Function Body / Expression rewriting
239//===----------------------------------------------------------------------===//
240
Chris Lattnere64b7772007-10-24 16:57:36 +0000241Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner311ff022007-10-16 22:36:42 +0000242 // Otherwise, just rewrite all children.
243 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
244 CI != E; ++CI)
Chris Lattner50754772007-10-17 21:28:00 +0000245 if (*CI)
Chris Lattnere64b7772007-10-24 16:57:36 +0000246 *CI = RewriteFunctionBody(*CI);
Steve Naroffebf2b562007-10-23 23:50:29 +0000247
248 // Handle specific things.
249 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
250 return RewriteAtEncode(AtEncode);
251
252 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S))
253 return RewriteMessageExpr(MessExpr);
254
Chris Lattnere64b7772007-10-24 16:57:36 +0000255 // Return this stmt unmodified.
256 return S;
Chris Lattner311ff022007-10-16 22:36:42 +0000257}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000258
Chris Lattnere64b7772007-10-24 16:57:36 +0000259Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattner01c57482007-10-17 22:35:30 +0000260 // Create a new string expression.
261 QualType StrType = Context->getPointerType(Context->CharTy);
262 Expr *Replacement = new StringLiteral("foo", 3, false, StrType,
263 SourceLocation(), SourceLocation());
264 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattnere64b7772007-10-24 16:57:36 +0000265 delete Exp;
266 return Replacement;
Chris Lattner311ff022007-10-16 22:36:42 +0000267}
268
Chris Lattnere64b7772007-10-24 16:57:36 +0000269Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
Steve Naroffebf2b562007-10-23 23:50:29 +0000270 assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
271 //Exp->dumpPretty();
272 //printf("\n");
273
274 // Synthesize a call to objc_msgSend().
275
276 // Get the type, we will need to reference it in a couple spots.
277 QualType msgSendType = MsgSendFunctionDecl->getType();
278
279 // Create a reference to the objc_msgSend() declaration.
280 DeclRefExpr *DRE = new DeclRefExpr(MsgSendFunctionDecl, msgSendType,
281 SourceLocation());
282
283 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerf04da132007-10-24 17:06:59 +0000284 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffebf2b562007-10-23 23:50:29 +0000285 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
286
287 const FunctionType *FT = msgSendType->getAsFunctionType();
288 CallExpr *CE = new CallExpr(ICE, 0, 0, FT->getResultType(),
289 SourceLocation());
290 Rewrite.ReplaceStmt(Exp, CE);
291 //Exp->dump();
292 //CE->dump();
Chris Lattnere64b7772007-10-24 16:57:36 +0000293
294 // FIXME: Walk the operands of Exp, setting them to null before we delete Exp.
295 // This will be needed when "CE" points to the operands of Exp.
296 delete Exp;
297 return CE;
Steve Naroffebf2b562007-10-23 23:50:29 +0000298}
299
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000300// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
301/// class methods.
302void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
303 int NumMethods,
304 const char *prefix,
305 const char *MethodKind,
306 const char *ClassName) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000307 static bool objc_impl_method = false;
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000308 if (NumMethods > 0 && !objc_impl_method) {
309 /* struct _objc_method {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000310 SEL _cmd;
311 char *method_types;
312 void *_imp;
313 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000314 */
315 printf("\nstruct _objc_method {\n");
316 printf("\tSEL _cmd;\n");
317 printf("\tchar *method_types;\n");
318 printf("\tvoid *_imp;\n");
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000319 printf("};\n");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000320 objc_impl_method = true;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000321 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000322 // Build _objc_method_list for class's methods if needed
323 if (NumMethods > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000324 /* struct _objc_method_list {
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000325 struct _objc_method_list *next_method;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000326 int method_count;
327 struct _objc_method method_list[method_count];
328 }
329 */
330 printf("\nstatic struct {\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000331 printf("\tstruct _objc_method_list *next_method;\n");
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000332 printf("\tint method_count;\n");
333 printf("\tstruct _objc_method method_list[%d];\n", NumMethods);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000334 printf("} _OBJC_%s%s_METHODS_%s "
335 "__attribute__ ((section (\"__OBJC, __inst_meth\")))= "
336 "{\n\t0, %d\n", prefix, MethodKind, ClassName, NumMethods);
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000337 for (int i = 0; i < NumMethods; i++)
338 // TODO: 1) method selector name may hav to go into their own section
339 // 2) encode method types for use here (which may have to go into
340 // __meth_var_types section, 3) Need method address as 3rd initializer.
341 printf("\t,(SEL)\"%s\", \"\", 0\n",
342 Methods[i]->getSelector().getName().c_str());
343 printf("};\n");
344 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000345}
346
347/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
348void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
349 int NumProtocols,
350 const char *prefix,
351 const char *ClassName) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000352 static bool objc_protocol_methods = false;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000353 if (NumProtocols > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000354 for (int i = 0; i < NumProtocols; i++) {
355 ObjcProtocolDecl *PDecl = Protocols[i];
356 // Output struct protocol_methods holder of method selector and type.
357 if (!objc_protocol_methods &&
358 (PDecl->getNumInstanceMethods() > 0
359 || PDecl->getNumClassMethods() > 0)) {
360 /* struct protocol_methods {
361 SEL _cmd;
362 char *method_types;
363 }
364 */
365 printf("\nstruct protocol_methods {\n");
366 printf("\tSEL _cmd;\n");
367 printf("\tchar *method_types;\n");
368 printf("};\n");
369 objc_protocol_methods = true;
370 }
371 // Output instance methods declared in this protocol.
372 /* struct _objc_protocol_method_list {
373 int protocol_method_count;
374 struct protocol_methods protocols[protocol_method_count];
375 }
376 */
377 int NumMethods = PDecl->getNumInstanceMethods();
378 if (NumMethods > 0) {
379 printf("\nstatic struct {\n");
380 printf("\tint protocol_method_count;\n");
381 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
382 printf("} _OBJC_PROTOCOL_INSTANCE_METHODS_%s "
383 "__attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
384 "{\n\t%d\n",PDecl->getName(), NumMethods);
385 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
386 for (int i = 0; i < NumMethods; i++)
387 // TODO: 1) method selector name may hav to go into their own section
388 // 2) encode method types for use here (which may have to go into
389 // __meth_var_types section.
390 printf("\t,(SEL)\"%s\", \"\"\n",
391 Methods[i]->getSelector().getName().c_str());
392 printf("};\n");
393 }
394
395 // Output class methods declared in this protocol.
396 NumMethods = PDecl->getNumClassMethods();
397 if (NumMethods > 0) {
398 printf("\nstatic struct {\n");
399 printf("\tint protocol_method_count;\n");
400 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
401 printf("} _OBJC_PROTOCOL_CLASS_METHODS_%s "
402 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
403 "{\n\t%d\n",PDecl->getName(), NumMethods);
404 ObjcMethodDecl **Methods = PDecl->getClassMethods();
405 for (int i = 0; i < NumMethods; i++)
406 // TODO: 1) method selector name may hav to go into their own section
407 // 2) encode method types for use here (which may have to go into
408 // __meth_var_types section.
409 printf("\t,(SEL)\"%s\", \"\"\n",
410 Methods[i]->getSelector().getName().c_str());
411 printf("};\n");
412 }
413 // Output:
414 /* struct _objc_protocol {
415 // Objective-C 1.0 extensions
416 struct _objc_protocol_extension *isa;
417 char *protocol_name;
418 struct _objc_protocol **protocol_list;
419 struct _objc__method_prototype_list *instance_methods;
420 struct _objc__method_prototype_list *class_methods;
421 };
422 */
423 static bool objc_protocol = false;
424 if (!objc_protocol) {
425 printf("\nstruct _objc_protocol {\n");
426 printf("\tstruct _objc_protocol_extension *isa;\n");
427 printf("\tchar *protocol_name;\n");
428 printf("\tstruct _objc_protocol **protocol_list;\n");
429 printf("\tstruct _objc__method_prototype_list *instance_methods;\n");
430 printf("\tstruct _objc__method_prototype_list *class_methods;\n");
431 printf("};\n");
432 objc_protocol = true;
433 }
434
435 printf("\nstatic struct _objc_protocol _OBJC_PROTOCOL_%s "
436 "__attribute__ ((section (\"__OBJC, __protocol\")))= "
437 "{\n\t0, \"%s\", 0, ", PDecl->getName(), PDecl->getName());
438 if (PDecl->getInstanceMethods() > 0)
439 printf("(struct _objc__method_prototype_list *)"
440 "&_OBJC_PROTOCOL_INSTANCE_METHODS_%s, ", PDecl->getName());
441 else
442 printf("0, ");
443 if (PDecl->getClassMethods() > 0)
444 printf("(struct _objc__method_prototype_list *)"
445 "&_OBJC_PROTOCOL_CLASS_METHODS_%s\n", PDecl->getName());
446 else
447 printf("0\n");
448 printf("};\n");
449 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000450 // Output the top lovel protocol meta-data for the class.
451 /* struct _objc_protocol_list {
452 struct _objc_protocol_list *next;
453 int protocol_count;
454 struct _objc_protocol *class_protocols[protocol_count];
455 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000456 */
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000457 printf("\nstatic struct {\n");
458 printf("\tstruct _objc_protocol_list *next;\n");
459 printf("\tint protocol_count;\n");
460 printf("\tstruct _objc_protocol *class_protocols[%d];\n"
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000461 "} _OBJC_%s_PROTOCOLS_%s "
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000462 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000463 "{\n\t0, %d\n",NumProtocols, prefix,
464 ClassName, NumProtocols);
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000465 for (int i = 0; i < NumProtocols; i++) {
466 ObjcProtocolDecl *PDecl = Protocols[i];
467 printf("\t,&_OBJC_PROTOCOL_%s \n",
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000468 PDecl->getName());
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000469 }
470 printf("};\n");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000471 }
472}
473
474/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
475/// implementation.
476void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl) {
477 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
478 // Find category declaration for this implementation.
479 ObjcCategoryDecl *CDecl;
480 for (CDecl = ClassDecl->getCategoryList(); CDecl;
481 CDecl = CDecl->getNextClassCategory())
482 if (CDecl->getIdentifier() == IDecl->getIdentifier())
483 break;
484 assert(CDecl && "RewriteObjcCategoryImplDecl - bad category");
485
486 char *FullCategoryName = (char*)alloca(
487 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
488 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
489
490 // Build _objc_method_list for class's instance methods if needed
491 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
492 IDecl->getNumInstanceMethods(),
493 "CATEGORY_", "INSTANCE", FullCategoryName);
494
495 // Build _objc_method_list for class's class methods if needed
496 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
497 IDecl->getNumClassMethods(),
498 "CATEGORY_", "CLASS", FullCategoryName);
499
500 // Protocols referenced in class declaration?
501 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
502 CDecl->getNumReferencedProtocols(),
503 "CATEGORY",
504 FullCategoryName);
505
506 /* struct _objc_category {
507 char *category_name;
508 char *class_name;
509 struct _objc_method_list *instance_methods;
510 struct _objc_method_list *class_methods;
511 struct _objc_protocol_list *protocols;
512 // Objective-C 1.0 extensions
513 uint32_t size; // sizeof (struct _objc_category)
514 struct _objc_property_list *instance_properties; // category's own
515 // @property decl.
516 };
517 */
518
519 static bool objc_category = false;
520 if (!objc_category) {
521 printf("\nstruct _objc_category {\n");
522 printf("\tchar *category_name;\n");
523 printf("\tchar *class_name;\n");
524 printf("\tstruct _objc_method_list *instance_methods;\n");
525 printf("\tstruct _objc_method_list *class_methods;\n");
526 printf("\tstruct _objc_protocol_list *protocols;\n");
527 printf("\tunsigned int size;\n");
528 printf("\tstruct _objc_property_list *instance_properties;\n");
529 printf("};\n");
530 objc_category = true;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000531 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000532 printf("\nstatic struct _objc_category _OBJC_CATEGORY_%s "
533 "__attribute__ ((section (\"__OBJC, __category\")))= {\n"
534 "\t\"%s\"\n\t, \"%s\"\n",FullCategoryName,
535 IDecl->getName(),
536 ClassDecl->getName());
537 if (IDecl->getNumInstanceMethods() > 0)
538 printf("\t, (struct _objc_method_list *)"
539 "&_OBJC_CATEGORY_INSTANCE_METHODS_%s\n",
540 FullCategoryName);
541 else
542 printf("\t, 0\n");
543 if (IDecl->getNumClassMethods() > 0)
544 printf("\t, (struct _objc_method_list *)"
545 "&_OBJC_CATEGORY_CLASS_METHODS_%s\n",
546 FullCategoryName);
547 else
548 printf("\t, 0\n");
549
550 if (CDecl->getNumReferencedProtocols() > 0)
551 printf("\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_%s\n",
552 FullCategoryName);
553 else
554 printf("\t, 0\n");
555 // size of struct _objc_category
556 printf("\t, 28, 0\n};\n");
557}
558
559//===----------------------------------------------------------------------===//
560// Meta Data Emission
561//===----------------------------------------------------------------------===//
562
563void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl) {
564 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
565
566 // Build _objc_ivar_list metadata for classes ivars if needed
567 int NumIvars = IDecl->getImplDeclNumIvars() > 0
568 ? IDecl->getImplDeclNumIvars()
569 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
570
571 if (NumIvars > 0) {
572 static bool objc_ivar = false;
573 if (!objc_ivar) {
574 /* struct _objc_ivar {
575 char *ivar_name;
576 char *ivar_type;
577 int ivar_offset;
578 };
579 */
580 printf("\nstruct _objc_ivar {\n");
581 printf("\tchar *ivar_name;\n");
582 printf("\tchar *ivar_type;\n");
583 printf("\tint ivar_offset;\n");
584 printf("};\n");
585 objc_ivar = true;
586 }
587
588 /* struct _objc_ivar_list {
589 int ivar_count;
590 struct _objc_ivar ivar_list[ivar_count];
591 };
592 */
593 printf("\nstatic struct {\n");
594 printf("\tint ivar_count;\n");
595 printf("\tstruct _objc_ivar ivar_list[%d];\n", NumIvars);
596 printf("} _OBJC_INSTANCE_VARIABLES_%s "
597 "__attribute__ ((section (\"__OBJC, __instance_vars\")))= "
598 "{\n\t%d\n",IDecl->getName(),
599 NumIvars);
600 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
601 ? IDecl->getImplDeclIVars()
602 : CDecl->getIntfDeclIvars();
603 for (int i = 0; i < NumIvars; i++)
604 // TODO: 1) ivar names may have to go to another section. 2) encode
605 // ivar_type type of each ivar . 3) compute and add ivar offset.
606 printf("\t,\"%s\", \"\", 0\n", Ivars[i]->getName());
607 printf("};\n");
608 }
609
610 // Build _objc_method_list for class's instance methods if needed
611 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
612 IDecl->getNumInstanceMethods(),
613 "", "INSTANCE", IDecl->getName());
614
615 // Build _objc_method_list for class's class methods if needed
616 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
617 IDecl->getNumClassMethods(),
618 "", "CLASS", IDecl->getName());
619
620 // Protocols referenced in class declaration?
621 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
622 CDecl->getNumIntfRefProtocols(),
623 "CLASS",
624 CDecl->getName());
625
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000626
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000627 // Declaration of class/meta-class metadata
628 /* struct _objc_class {
629 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000630 const char *super_class_name;
631 char *name;
632 long version;
633 long info;
634 long instance_size;
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000635 struct _objc_ivar_list *ivars;
636 struct _objc_method_list *methods;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000637 struct objc_cache *cache;
638 struct objc_protocol_list *protocols;
639 const char *ivar_layout;
640 struct _objc_class_ext *ext;
641 };
642 */
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000643 static bool objc_class = false;
644 if (!objc_class) {
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000645 printf("\nstruct _objc_class {\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000646 printf("\tstruct _objc_class *isa;\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000647 printf("\tconst char *super_class_name;\n");
648 printf("\tchar *name;\n");
649 printf("\tlong version;\n");
650 printf("\tlong info;\n");
651 printf("\tlong instance_size;\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000652 printf("\tstruct _objc_ivar_list *ivars;\n");
653 printf("\tstruct _objc_method_list *methods;\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000654 printf("\tstruct objc_cache *cache;\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000655 printf("\tstruct _objc_protocol_list *protocols;\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000656 printf("\tconst char *ivar_layout;\n");
657 printf("\tstruct _objc_class_ext *ext;\n");
658 printf("};\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000659 objc_class = true;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000660 }
661
662 // Meta-class metadata generation.
663 ObjcInterfaceDecl *RootClass = 0;
664 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
665 while (SuperClass) {
666 RootClass = SuperClass;
667 SuperClass = SuperClass->getSuperClass();
668 }
669 SuperClass = CDecl->getSuperClass();
670
671 printf("\nstatic struct _objc_class _OBJC_METACLASS_%s "
672 "__attribute__ ((section (\"__OBJC, __meta_class\")))= "
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000673 "{\n\t(struct _objc_class *)\"%s\"",
674 CDecl->getName(), RootClass ? RootClass->getName()
675 : CDecl->getName());
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000676 if (SuperClass)
677 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
678 else
679 printf(", 0, \"%s\"", CDecl->getName());
680 // FIXME: better way of getting size struct _objc_class (48)
681 // TODO: 'ivars' field for root class is currently set to 0.
682 // 'info' field is initialized to CLS_META(2) for metaclass
683 printf(", 0,2,48,0");
684 if (CDecl->getNumClassMethods() > 0)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000685 printf("\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_%s\n",
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000686 CDecl->getName());
687 else
688 printf(", 0\n");
Fariborz Jahanian454cb012007-10-24 20:54:23 +0000689 if (CDecl->getNumIntfRefProtocols() > 0)
690 printf("\t,0,(struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_%s,0,0\n",
691 CDecl->getName());
692 else
693 printf("\t,0,0,0,0\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000694 printf("};\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000695
696 // class metadata generation.
697 printf("\nstatic struct _objc_class _OBJC_CLASS_%s "
698 "__attribute__ ((section (\"__OBJC, __class\")))= "
699 "{\n\t&_OBJC_METACLASS_%s", CDecl->getName(), CDecl->getName());
700 if (SuperClass)
701 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
702 else
703 printf(", 0, \"%s\"", CDecl->getName());
704 // 'info' field is initialized to CLS_CLASS(1) for class
705 // TODO: instance_size is curently set to 0.
706 printf(", 0,1,0");
707 if (NumIvars > 0)
708 printf(", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_%s\n\t",
709 CDecl->getName());
710 else
711 printf(",0");
712 if (IDecl->getNumInstanceMethods() > 0)
713 printf(", (struct _objc_method_list*)&_OBJC_INSTANCE_METHODS_%s, 0\n\t",
714 CDecl->getName());
715 else
716 printf(",0,0");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000717 if (CDecl->getNumIntfRefProtocols() > 0)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000718 printf(", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_%s, 0,0\n",
719 CDecl->getName());
720 else
721 printf(",0,0,0\n");
722 printf("};\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000723}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000724
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000725void RewriteTest::WriteObjcMetaData() {
726 int ClsDefCount = ClassImplementation.size();
727 int CatDefCount = CategoryImplementation.size();
728 if (ClsDefCount == 0 && CatDefCount == 0)
729 return;
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000730
Fariborz Jahanian454cb012007-10-24 20:54:23 +0000731 // TODO: This is temporary until we decide how to access objc types in a
732 // c program
733 printf("\n#include <Objc/objc.h>\n");
734
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000735 // For each implemented class, write out all its meta data.
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000736 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000737 RewriteObjcClassMetaData(ClassImplementation[i]);
738
739 // For each implemented category, write out all its meta data.
740 for (int i = 0; i < CatDefCount; i++)
741 RewriteObjcCategoryImplDecl(CategoryImplementation[i]);
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000742
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000743 // Write objc_symtab metadata
744 /*
745 struct _objc_symtab
746 {
747 long sel_ref_cnt;
748 SEL *refs;
749 short cls_def_cnt;
750 short cat_def_cnt;
751 void *defs[cls_def_cnt + cat_def_cnt];
752 };
753 */
754
755 printf("\nstruct _objc_symtab {\n");
756 printf("\tlong sel_ref_cnt;\n");
757 printf("\tSEL *refs;\n");
758 printf("\tshort cls_def_cnt;\n");
759 printf("\tshort cat_def_cnt;\n");
760 printf("\tvoid *defs[%d];\n", ClsDefCount + CatDefCount);
761 printf("};\n\n");
762
763 printf("static struct _objc_symtab "
Chris Lattnerf04da132007-10-24 17:06:59 +0000764 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n");
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000765 printf("\t0, 0, %d, %d\n", ClsDefCount, CatDefCount);
766 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000767 printf("\t,&_OBJC_CLASS_%s\n", ClassImplementation[i]->getName());
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000768
769 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000770 printf("\t,&_OBJC_CATEGORY_%s_%s\n",
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000771 CategoryImplementation[i]->getClassInterface()->getName(),
772 CategoryImplementation[i]->getName());
773
774 printf("};\n\n");
775
776 // Write objc_module metadata
777
778 /*
779 struct _objc_module {
780 long version;
781 long size;
782 const char *name;
783 struct _objc_symtab *symtab;
784 }
785 */
786
787 printf("\nstruct _objc_module {\n");
788 printf("\tlong version;\n");
789 printf("\tlong size;\n");
790 printf("\tconst char *name;\n");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000791 printf("\tstruct _objc_symtab *symtab;\n");
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000792 printf("};\n\n");
793 printf("static struct _objc_module "
794 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n");
795 printf("\t%d, %d, \"\", &_OBJC_SYMBOLS\n", OBJC_ABI_VERSION, 16);
796 printf("};\n\n");
797}
Chris Lattner311ff022007-10-16 22:36:42 +0000798