blob: 7cf1342591a6fb22abe3ccf0f10bffa2021b1b97 [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"
Chris Lattnerb429ae42007-10-11 00:43:27 +000019using namespace clang;
20
21
22namespace {
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;
31 static const int OBJC_ABI_VERSION =7 ;
Chris Lattnerb429ae42007-10-11 00:43:27 +000032 public:
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000033 void Initialize(ASTContext &context, unsigned mainFileID) {
34 Context = &context;
35 SM = &Context->SourceMgr;
Chris Lattner569faa62007-10-11 18:38:32 +000036 MainFileID = mainFileID;
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000037 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattnerb429ae42007-10-11 00:43:27 +000038 }
39
40 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner569faa62007-10-11 18:38:32 +000041
Chris Lattner74db1682007-10-16 21:07:07 +000042 void HandleDeclInMainFile(Decl *D);
43 void RewriteInclude(SourceLocation Loc);
Chris Lattner6fe8b272007-10-16 22:36:42 +000044
45 void RewriteFunctionBody(Stmt *S);
46 void RewriteAtEncode(ObjCEncodeExpr *Exp);
Steve Naroff4c4abed2007-10-23 20:20:08 +000047 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
48
Fariborz Jahanian45d52f72007-10-18 22:09:03 +000049 void WriteObjcClassMetaData(ObjcImplementationDecl *IDecl);
Fariborz Jahanian640a01f2007-10-18 19:23:00 +000050 void WriteObjcMetaData();
51
Chris Lattner569faa62007-10-11 18:38:32 +000052 ~RewriteTest();
Chris Lattnerb429ae42007-10-11 00:43:27 +000053 };
54}
55
Chris Lattner569faa62007-10-11 18:38:32 +000056ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattnerb429ae42007-10-11 00:43:27 +000057
Chris Lattner569faa62007-10-11 18:38:32 +000058void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner74db1682007-10-16 21:07:07 +000059 // Two cases: either the decl could be in the main file, or it could be in a
60 // #included file. If the former, rewrite it now. If the later, check to see
61 // if we rewrote the #include/#import.
62 SourceLocation Loc = D->getLocation();
63 Loc = SM->getLogicalLoc(Loc);
64
65 // If this is for a builtin, ignore it.
66 if (Loc.isInvalid()) return;
67
68 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
69 return HandleDeclInMainFile(D);
70
71 RewriteInclude(Loc);
72}
73
74void RewriteTest::RewriteInclude(SourceLocation Loc) {
75 // Rip up the #include stack to the main file.
76 SourceLocation IncLoc = Loc, NextLoc = Loc;
77 do {
78 IncLoc = Loc;
79 Loc = SM->getLogicalLoc(NextLoc);
80 NextLoc = SM->getIncludeLoc(Loc);
81 } while (!NextLoc.isInvalid());
82
83 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
84 // IncLoc indicates the header that was included if it is useful.
85 IncLoc = SM->getLogicalLoc(IncLoc);
86 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
87 Loc == LastIncLoc)
88 return;
89 LastIncLoc = Loc;
90
91 unsigned IncCol = SM->getColumnNumber(Loc);
92 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
93
94 // Replace the #import with #include.
95 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
96}
97
98/// HandleDeclInMainFile - This is called for each top-level decl defined in the
99/// main file of the input.
100void RewriteTest::HandleDeclInMainFile(Decl *D) {
Chris Lattner6fe8b272007-10-16 22:36:42 +0000101 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
102 if (Stmt *Body = FD->getBody())
103 RewriteFunctionBody(Body);
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000104
105 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
106 ClassImplementation.push_back(CI);
107 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
108 CategoryImplementation.push_back(CI);
Steve Naroff4c4abed2007-10-23 20:20:08 +0000109 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
110 RewriteForwardClassDecl(CD);
Chris Lattner74db1682007-10-16 21:07:07 +0000111 // Nothing yet.
Chris Lattner569faa62007-10-11 18:38:32 +0000112}
113
114
Chris Lattner6fe8b272007-10-16 22:36:42 +0000115void RewriteTest::RewriteFunctionBody(Stmt *S) {
116 // Handle specific things.
117 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
118 return RewriteAtEncode(AtEncode);
119
120 // Otherwise, just rewrite all children.
121 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
122 CI != E; ++CI)
Chris Lattnere33506b2007-10-17 21:28:00 +0000123 if (*CI)
124 RewriteFunctionBody(*CI);
Chris Lattner6fe8b272007-10-16 22:36:42 +0000125}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000126
Chris Lattner6fe8b272007-10-16 22:36:42 +0000127void RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattnerbf0bfa62007-10-17 22:35:30 +0000128 // Create a new string expression.
129 QualType StrType = Context->getPointerType(Context->CharTy);
130 Expr *Replacement = new StringLiteral("foo", 3, false, StrType,
131 SourceLocation(), SourceLocation());
132 Rewrite.ReplaceStmt(Exp, Replacement);
133 delete Replacement;
Chris Lattner6fe8b272007-10-16 22:36:42 +0000134}
135
Steve Naroff4c4abed2007-10-23 20:20:08 +0000136void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
137 int numDecls = ClassDecl->getNumForwardDecls();
138 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
139
140 // Get the start location and compute the semi location.
141 SourceLocation startLoc = ClassDecl->getLocation();
142 const char *startBuf = SM->getCharacterData(startLoc);
143 const char *semiPtr = startBuf;
144 while (semiPtr && (*semiPtr != ';')) semiPtr++;
145
146 // Translate to typedef's that forward reference structs with the same name
147 // as the class. As a convenience, we include the original declaration
148 // as a comment.
149 std::string typedefString;
150 typedefString += "// ";
151 typedefString.append(startBuf, semiPtr-startBuf+1);
152 typedefString += "\n";
153 for (int i = 0; i < numDecls; i++) {
154 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
155 typedefString += "typedef struct ";
156 typedefString += ForwardDecl->getName();
157 typedefString += " ";
158 typedefString += ForwardDecl->getName();
159 typedefString += ";\n";
160 }
161
162 // Replace the @class with typedefs corresponding to the classes.
163 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
164 typedefString.c_str(), typedefString.size());
165}
166
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000167void RewriteTest::WriteObjcClassMetaData(ObjcImplementationDecl *IDecl) {
168 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
169
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000170 // Build _objc_ivar_list metadata for classes ivars if needed
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000171 int NumIvars = IDecl->getImplDeclNumIvars() > 0
172 ? IDecl->getImplDeclNumIvars()
173 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
174
175 if (NumIvars > 0) {
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000176 static bool objc_ivar = false;
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000177 if (!objc_ivar) {
178 /* struct _objc_ivar {
179 char *ivar_name;
180 char *ivar_type;
181 int ivar_offset;
182 };
183 */
184 printf("\nstruct _objc_ivar {\n");
185 printf("\tchar *ivar_name;\n");
186 printf("\tchar *ivar_type;\n");
187 printf("\tint ivar_offset;\n");
188 printf("};\n");
189 objc_ivar = true;
190 }
191
192 /* struct _objc_ivar_list {
193 int ivar_count;
194 struct _objc_ivar ivar_list[ivar_count];
195 };
196 */
197 printf("\nstatic struct {\n");
198 printf("\tint ivar_count;\n");
199 printf("\tstruct _objc_ivar ivar_list[%d];\n", NumIvars);
200 printf("} _OBJC_INSTANCE_VARIABLES_%s "
201 "__attribute__ ((section (\"__OBJC, __instance_vars\")))= "
202 "{\n\t%d\n",IDecl->getName(),
203 NumIvars);
204 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
205 ? IDecl->getImplDeclIVars()
206 : CDecl->getIntfDeclIvars();
207 for (int i = 0; i < NumIvars; i++)
208 // TODO: 1) ivar names may have to go to another section. 2) encode
209 // ivar_type type of each ivar . 3) compute and add ivar offset.
210 printf("\t,\"%s\", \"\", 0\n", Ivars[i]->getName());
211 printf("};\n");
212 }
213
Fariborz Jahanian04455192007-10-22 21:41:37 +0000214 // Build _objc_method for class's instance or class methods metadata if needed
215 static bool objc_impl_method = false;
216 if (IDecl->getNumInstanceMethods() > 0 || IDecl->getNumClassMethods() > 0) {
217 if (!objc_impl_method) {
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000218 /* struct _objc_method {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000219 SEL _cmd;
220 char *method_types;
221 void *_imp;
222 }
223 */
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000224 printf("\nstruct _objc_method {\n");
225 printf("\tSEL _cmd;\n");
226 printf("\tchar *method_types;\n");
227 printf("\tvoid *_imp;\n");
228 printf("};\n");
Fariborz Jahanian04455192007-10-22 21:41:37 +0000229 objc_impl_method = true;
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000230 }
Fariborz Jahanian04455192007-10-22 21:41:37 +0000231 }
232 // Build _objc_method_list for class's instance methods if needed
233 if (IDecl->getNumInstanceMethods() > 0) {
234 int NumMethods = IDecl->getNumInstanceMethods();
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000235 /* struct _objc_method_list {
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000236 struct _objc_method_list *next_method;
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000237 int method_count;
238 struct _objc_method method_list[method_count];
239 }
240 */
241 printf("\nstatic struct {\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000242 printf("\tstruct _objc_method_list *next_method;\n");
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000243 printf("\tint method_count;\n");
244 printf("\tstruct _objc_method method_list[%d];\n", NumMethods);
245 printf("} _OBJC_INSTANCE_METHODS_%s "
246 "__attribute__ ((section (\"__OBJC, __inst_meth\")))= "
247 "{\n\t0, %d\n", IDecl->getName(), NumMethods);
248 ObjcMethodDecl **Methods = IDecl->getInstanceMethods();
249 for (int i = 0; i < NumMethods; i++)
250 // TODO: 1) method selector name may hav to go into their own section
251 // 2) encode method types for use here (which may have to go into
252 // __meth_var_types section, 3) Need method address as 3rd initializer.
253 printf("\t,(SEL)\"%s\", \"\", 0\n",
254 Methods[i]->getSelector().getName().c_str());
255 printf("};\n");
256 }
257
Fariborz Jahanian04455192007-10-22 21:41:37 +0000258 // Build _objc_method_list for class's class methods if needed
259 if (IDecl->getNumClassMethods() > 0) {
260 int NumMethods = IDecl->getNumClassMethods();
261 /* struct _objc_method_list {
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000262 struct _objc_method_list *next_method;
Fariborz Jahanian04455192007-10-22 21:41:37 +0000263 int method_count;
264 struct _objc_method method_list[method_count];
265 }
266 */
267 printf("\nstatic struct {\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000268 printf("\tstruct _objc_method_list *next_method;\n");
Fariborz Jahanian04455192007-10-22 21:41:37 +0000269 printf("\tint method_count;\n");
270 printf("\tstruct _objc_method method_list[%d];\n", NumMethods);
271 printf("} _OBJC_CLASS_METHODS_%s "
272 "__attribute__ ((section (\"__OBJC, __cls_meth\")))= "
273 "{\n\t0, %d\n", IDecl->getName(), NumMethods);
274 ObjcMethodDecl **Methods = IDecl->getClassMethods();
275 for (int i = 0; i < NumMethods; i++)
276 // TODO: 1) method selector name may hav to go into their own section
277 // 2) encode method types for use here (which may have to go into
278 // __meth_var_types section, 3) Need method address as 3rd initializer.
279 printf("\t,(SEL)\"%s\", \"\", 0\n",
280 Methods[i]->getSelector().getName().c_str());
281 printf("};\n");
282 }
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000283
Fariborz Jahanian04455192007-10-22 21:41:37 +0000284 // Protocols referenced in class declaration?
285 static bool objc_protocol_methods = false;
286 int NumProtocols = CDecl->getNumIntfRefProtocols();
287 if (NumProtocols > 0) {
288 ObjcProtocolDecl **Protocols = CDecl->getReferencedProtocols();
289 for (int i = 0; i < NumProtocols; i++) {
290 ObjcProtocolDecl *PDecl = Protocols[i];
291 // Output struct protocol_methods holder of method selector and type.
292 if (!objc_protocol_methods &&
293 (PDecl->getNumInstanceMethods() > 0
294 || PDecl->getNumClassMethods() > 0)) {
295 /* struct protocol_methods {
296 SEL _cmd;
297 char *method_types;
298 }
299 */
300 printf("\nstruct protocol_methods {\n");
301 printf("\tSEL _cmd;\n");
302 printf("\tchar *method_types;\n");
303 printf("};\n");
304 objc_protocol_methods = true;
305 }
306 // Output instance methods declared in this protocol.
307 /* struct _objc_protocol_method_list {
308 int protocol_method_count;
309 struct protocol_methods protocols[protocol_method_count];
310 }
311 */
312 int NumMethods = PDecl->getNumInstanceMethods();
313 if (NumMethods > 0) {
314 printf("\nstatic struct {\n");
315 printf("\tint protocol_method_count;\n");
316 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
317 printf("} _OBJC_PROTOCOL_INSTANCE_METHODS_%s "
318 "__attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
319 "{\n\t%d\n",PDecl->getName(), NumMethods);
320 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
321 for (int i = 0; i < NumMethods; i++)
322 // TODO: 1) method selector name may hav to go into their own section
323 // 2) encode method types for use here (which may have to go into
324 // __meth_var_types section.
325 printf("\t,(SEL)\"%s\", \"\"\n",
326 Methods[i]->getSelector().getName().c_str());
327 printf("};\n");
328 }
329
330 // Output class methods declared in this protocol.
331 NumMethods = PDecl->getNumClassMethods();
332 if (NumMethods > 0) {
333 printf("\nstatic struct {\n");
334 printf("\tint protocol_method_count;\n");
335 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
336 printf("} _OBJC_PROTOCOL_CLASS_METHODS_%s "
337 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
338 "{\n\t%d\n",PDecl->getName(), NumMethods);
339 ObjcMethodDecl **Methods = PDecl->getClassMethods();
340 for (int i = 0; i < NumMethods; i++)
341 // TODO: 1) method selector name may hav to go into their own section
342 // 2) encode method types for use here (which may have to go into
343 // __meth_var_types section.
344 printf("\t,(SEL)\"%s\", \"\"\n",
345 Methods[i]->getSelector().getName().c_str());
346 printf("};\n");
347 }
348 // Output:
349 /* struct _objc_protocol {
350 // Objective-C 1.0 extensions
351 struct _objc_protocol_extension *isa;
352 char *protocol_name;
353 struct _objc_protocol **protocol_list;
354 struct _objc__method_prototype_list *instance_methods;
355 struct _objc__method_prototype_list *class_methods;
356 };
357 */
358 static bool objc_protocol = false;
359 if (!objc_protocol) {
360 printf("\nstruct _objc_protocol {\n");
361 printf("\tstruct _objc_protocol_extension *isa;\n");
362 printf("\tchar *protocol_name;\n");
363 printf("\tstruct _objc_protocol **protocol_list;\n");
364 printf("\tstruct _objc__method_prototype_list *instance_methods;\n");
365 printf("\tstruct _objc__method_prototype_list *class_methods;\n");
366 printf("};\n");
367 objc_protocol = true;
368 }
369
370 printf("\nstatic struct _objc_protocol _OBJC_PROTOCOL_%s "
371 "__attribute__ ((section (\"__OBJC, __protocol\")))= "
372 "{\n\t0, \"%s\", 0, ", PDecl->getName(), PDecl->getName());
373 if (PDecl->getInstanceMethods() > 0)
374 printf("(struct _objc__method_prototype_list *)"
375 "&_OBJC_PROTOCOL_INSTANCE_METHODS_%s, ", PDecl->getName());
376 else
377 printf("0, ");
378 if (PDecl->getClassMethods() > 0)
379 printf("(struct _objc__method_prototype_list *)"
380 "&_OBJC_PROTOCOL_CLASS_METHODS_%s\n", PDecl->getName());
381 else
382 printf("0\n");
383 printf("};\n");
384 }
385 }
386 if (NumProtocols > 0) {
387 // Output the top lovel protocol meta-data for the class.
388 /* struct _objc_protocol_list {
389 struct _objc_protocol_list *next;
390 int protocol_count;
391 struct _objc_protocol *class_protocols[protocol_count];
392 }
393 */
394 printf("\nstatic struct {\n");
395 printf("\tstruct _objc_protocol_list *next;\n");
396 printf("\tint protocol_count;\n");
397 printf("\tstruct _objc_protocol *class_protocols[%d];\n"
398 "} _OBJC_CLASS_PROTOCOLS_%s "
399 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
400 "{\n\t0, %d\n",NumProtocols, CDecl->getName(), NumProtocols);
401 ObjcProtocolDecl **Protocols = CDecl->getReferencedProtocols();
402 for (int i = 0; i < NumProtocols; i++) {
403 ObjcProtocolDecl *PDecl = Protocols[i];
404 printf("\t,&_OBJC_PROTOCOL_%s \n",
405 PDecl->getName());
406 }
407 printf("};\n");
408 }
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000409
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000410 // Declaration of class/meta-class metadata
411 /* struct _objc_class {
412 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000413 const char *super_class_name;
414 char *name;
415 long version;
416 long info;
417 long instance_size;
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000418 struct _objc_ivar_list *ivars;
419 struct _objc_method_list *methods;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000420 struct objc_cache *cache;
421 struct objc_protocol_list *protocols;
422 const char *ivar_layout;
423 struct _objc_class_ext *ext;
424 };
425 */
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000426 static bool objc_class = false;
427 if (!objc_class) {
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000428 printf("\nstruct _objc_class {\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000429 printf("\tstruct _objc_class *isa;\n");
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000430 printf("\tconst char *super_class_name;\n");
431 printf("\tchar *name;\n");
432 printf("\tlong version;\n");
433 printf("\tlong info;\n");
434 printf("\tlong instance_size;\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000435 printf("\tstruct _objc_ivar_list *ivars;\n");
436 printf("\tstruct _objc_method_list *methods;\n");
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000437 printf("\tstruct objc_cache *cache;\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000438 printf("\tstruct _objc_protocol_list *protocols;\n");
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000439 printf("\tconst char *ivar_layout;\n");
440 printf("\tstruct _objc_class_ext *ext;\n");
441 printf("};\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000442 objc_class = true;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000443 }
444
445 // Meta-class metadata generation.
446 ObjcInterfaceDecl *RootClass = 0;
447 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
448 while (SuperClass) {
449 RootClass = SuperClass;
450 SuperClass = SuperClass->getSuperClass();
451 }
452 SuperClass = CDecl->getSuperClass();
453
454 printf("\nstatic struct _objc_class _OBJC_METACLASS_%s "
455 "__attribute__ ((section (\"__OBJC, __meta_class\")))= "
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000456 "{\n\t(struct _objc_class *)\"%s\"",
457 CDecl->getName(), RootClass ? RootClass->getName()
458 : CDecl->getName());
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000459 if (SuperClass)
460 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
461 else
462 printf(", 0, \"%s\"", CDecl->getName());
463 // FIXME: better way of getting size struct _objc_class (48)
464 // TODO: 'ivars' field for root class is currently set to 0.
465 // 'info' field is initialized to CLS_META(2) for metaclass
466 printf(", 0,2,48,0");
467 if (CDecl->getNumClassMethods() > 0)
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000468 printf("\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_%s\n",
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000469 CDecl->getName());
470 else
471 printf(", 0\n");
472 printf("\t,0,0,0,0\n");
473 printf("};\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000474
475 // class metadata generation.
476 printf("\nstatic struct _objc_class _OBJC_CLASS_%s "
477 "__attribute__ ((section (\"__OBJC, __class\")))= "
478 "{\n\t&_OBJC_METACLASS_%s", CDecl->getName(), CDecl->getName());
479 if (SuperClass)
480 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
481 else
482 printf(", 0, \"%s\"", CDecl->getName());
483 // 'info' field is initialized to CLS_CLASS(1) for class
484 // TODO: instance_size is curently set to 0.
485 printf(", 0,1,0");
486 if (NumIvars > 0)
487 printf(", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_%s\n\t",
488 CDecl->getName());
489 else
490 printf(",0");
491 if (IDecl->getNumInstanceMethods() > 0)
492 printf(", (struct _objc_method_list*)&_OBJC_INSTANCE_METHODS_%s, 0\n\t",
493 CDecl->getName());
494 else
495 printf(",0,0");
496 if (NumProtocols > 0)
497 printf(", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_%s, 0,0\n",
498 CDecl->getName());
499 else
500 printf(",0,0,0\n");
501 printf("};\n");
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000502}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000503
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000504void RewriteTest::WriteObjcMetaData() {
505 int ClsDefCount = ClassImplementation.size();
506 int CatDefCount = CategoryImplementation.size();
507 if (ClsDefCount == 0 && CatDefCount == 0)
508 return;
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000509
510 // For each defined class, write out all its meta data.
511 for (int i = 0; i < ClsDefCount; i++)
512 WriteObjcClassMetaData(ClassImplementation[i]);
513
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000514 // Write objc_symtab metadata
515 /*
516 struct _objc_symtab
517 {
518 long sel_ref_cnt;
519 SEL *refs;
520 short cls_def_cnt;
521 short cat_def_cnt;
522 void *defs[cls_def_cnt + cat_def_cnt];
523 };
524 */
525
526 printf("\nstruct _objc_symtab {\n");
527 printf("\tlong sel_ref_cnt;\n");
528 printf("\tSEL *refs;\n");
529 printf("\tshort cls_def_cnt;\n");
530 printf("\tshort cat_def_cnt;\n");
531 printf("\tvoid *defs[%d];\n", ClsDefCount + CatDefCount);
532 printf("};\n\n");
533
534 printf("static struct _objc_symtab "
535 "_OBJC_SYMBOLS __attribute__ ((section (\"__OBJC, __symbols\")))= {\n");
536 printf("\t0, 0, %d, %d\n", ClsDefCount, CatDefCount);
537 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000538 printf("\t,&_OBJC_CLASS_%s\n", ClassImplementation[i]->getName());
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000539
540 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000541 printf("\t,&_OBJC_CATEGORY_%s_%s\n",
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000542 CategoryImplementation[i]->getClassInterface()->getName(),
543 CategoryImplementation[i]->getName());
544
545 printf("};\n\n");
546
547 // Write objc_module metadata
548
549 /*
550 struct _objc_module {
551 long version;
552 long size;
553 const char *name;
554 struct _objc_symtab *symtab;
555 }
556 */
557
558 printf("\nstruct _objc_module {\n");
559 printf("\tlong version;\n");
560 printf("\tlong size;\n");
561 printf("\tconst char *name;\n");
562 printf("\tstruct _objc_symtab *symtab;");
563 printf("};\n\n");
564 printf("static struct _objc_module "
565 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n");
566 printf("\t%d, %d, \"\", &_OBJC_SYMBOLS\n", OBJC_ABI_VERSION, 16);
567 printf("};\n\n");
568}
Chris Lattner6fe8b272007-10-16 22:36:42 +0000569
Chris Lattner569faa62007-10-11 18:38:32 +0000570RewriteTest::~RewriteTest() {
Chris Lattner569faa62007-10-11 18:38:32 +0000571 // Get the top-level buffer that this corresponds to.
572 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
573 const char *MainBufStart = MainBuf.first;
574 const char *MainBufEnd = MainBuf.second;
575
576 // Loop over the whole file, looking for tabs.
577 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
578 if (*BufPtr != '\t')
579 continue;
580
581 // Okay, we found a tab. This tab will turn into at least one character,
582 // but it depends on which 'virtual column' it is in. Compute that now.
583 unsigned VCol = 0;
584 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
585 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
586 ++VCol;
587
588 // Okay, now that we know the virtual column, we know how many spaces to
589 // insert. We assume 8-character tab-stops.
590 unsigned Spaces = 8-(VCol & 7);
591
592 // Get the location of the tab.
593 SourceLocation TabLoc =
594 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
595
596 // Rewrite the single tab character into a sequence of spaces.
Chris Lattnere471a3b2007-10-13 00:46:29 +0000597 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
Chris Lattner569faa62007-10-11 18:38:32 +0000598 }
599
600 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
601 // we are done.
602 if (const RewriteBuffer *RewriteBuf =
603 Rewrite.getRewriteBufferFor(MainFileID)) {
Chris Lattner3cfe3d32007-10-13 00:11:23 +0000604 printf("Changed:\n");
605 std::string S(RewriteBuf->begin(), RewriteBuf->end());
606 printf("%s\n", S.c_str());
Chris Lattner569faa62007-10-11 18:38:32 +0000607 } else {
608 printf("No changes\n");
609 }
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000610 // Rewrite Objective-c meta data*
611 WriteObjcMetaData();
Chris Lattnerb429ae42007-10-11 00:43:27 +0000612}