blob: cf812a284f891cb7aea418e3c3015e588ca2d8a8 [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);
Chris Lattner74db1682007-10-16 21:07:07 +000047
Fariborz Jahanian45d52f72007-10-18 22:09:03 +000048 void WriteObjcClassMetaData(ObjcImplementationDecl *IDecl);
Fariborz Jahanian640a01f2007-10-18 19:23:00 +000049 void WriteObjcMetaData();
50
Chris Lattner569faa62007-10-11 18:38:32 +000051 ~RewriteTest();
Chris Lattnerb429ae42007-10-11 00:43:27 +000052 };
53}
54
Chris Lattner569faa62007-10-11 18:38:32 +000055ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattnerb429ae42007-10-11 00:43:27 +000056
Chris Lattner569faa62007-10-11 18:38:32 +000057void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner74db1682007-10-16 21:07:07 +000058 // Two cases: either the decl could be in the main file, or it could be in a
59 // #included file. If the former, rewrite it now. If the later, check to see
60 // if we rewrote the #include/#import.
61 SourceLocation Loc = D->getLocation();
62 Loc = SM->getLogicalLoc(Loc);
63
64 // If this is for a builtin, ignore it.
65 if (Loc.isInvalid()) return;
66
67 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
68 return HandleDeclInMainFile(D);
69
70 RewriteInclude(Loc);
71}
72
73void RewriteTest::RewriteInclude(SourceLocation Loc) {
74 // Rip up the #include stack to the main file.
75 SourceLocation IncLoc = Loc, NextLoc = Loc;
76 do {
77 IncLoc = Loc;
78 Loc = SM->getLogicalLoc(NextLoc);
79 NextLoc = SM->getIncludeLoc(Loc);
80 } while (!NextLoc.isInvalid());
81
82 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
83 // IncLoc indicates the header that was included if it is useful.
84 IncLoc = SM->getLogicalLoc(IncLoc);
85 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
86 Loc == LastIncLoc)
87 return;
88 LastIncLoc = Loc;
89
90 unsigned IncCol = SM->getColumnNumber(Loc);
91 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
92
93 // Replace the #import with #include.
94 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
95}
96
97/// HandleDeclInMainFile - This is called for each top-level decl defined in the
98/// main file of the input.
99void RewriteTest::HandleDeclInMainFile(Decl *D) {
Chris Lattner6fe8b272007-10-16 22:36:42 +0000100 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
101 if (Stmt *Body = FD->getBody())
102 RewriteFunctionBody(Body);
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000103
104 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
105 ClassImplementation.push_back(CI);
106 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
107 CategoryImplementation.push_back(CI);
Chris Lattner74db1682007-10-16 21:07:07 +0000108 // Nothing yet.
Chris Lattner569faa62007-10-11 18:38:32 +0000109}
110
111
Chris Lattner6fe8b272007-10-16 22:36:42 +0000112void RewriteTest::RewriteFunctionBody(Stmt *S) {
113 // Handle specific things.
114 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
115 return RewriteAtEncode(AtEncode);
116
117 // Otherwise, just rewrite all children.
118 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
119 CI != E; ++CI)
Chris Lattnere33506b2007-10-17 21:28:00 +0000120 if (*CI)
121 RewriteFunctionBody(*CI);
Chris Lattner6fe8b272007-10-16 22:36:42 +0000122}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000123
Chris Lattner6fe8b272007-10-16 22:36:42 +0000124void RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattnerbf0bfa62007-10-17 22:35:30 +0000125 // Create a new string expression.
126 QualType StrType = Context->getPointerType(Context->CharTy);
127 Expr *Replacement = new StringLiteral("foo", 3, false, StrType,
128 SourceLocation(), SourceLocation());
129 Rewrite.ReplaceStmt(Exp, Replacement);
130 delete Replacement;
Chris Lattner6fe8b272007-10-16 22:36:42 +0000131}
132
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000133void RewriteTest::WriteObjcClassMetaData(ObjcImplementationDecl *IDecl) {
134 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
135
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000136 // Build _objc_ivar_list metadata for classes ivars if needed
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000137 int NumIvars = IDecl->getImplDeclNumIvars() > 0
138 ? IDecl->getImplDeclNumIvars()
139 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
140
141 if (NumIvars > 0) {
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000142 static bool objc_ivar = false;
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000143 if (!objc_ivar) {
144 /* struct _objc_ivar {
145 char *ivar_name;
146 char *ivar_type;
147 int ivar_offset;
148 };
149 */
150 printf("\nstruct _objc_ivar {\n");
151 printf("\tchar *ivar_name;\n");
152 printf("\tchar *ivar_type;\n");
153 printf("\tint ivar_offset;\n");
154 printf("};\n");
155 objc_ivar = true;
156 }
157
158 /* struct _objc_ivar_list {
159 int ivar_count;
160 struct _objc_ivar ivar_list[ivar_count];
161 };
162 */
163 printf("\nstatic struct {\n");
164 printf("\tint ivar_count;\n");
165 printf("\tstruct _objc_ivar ivar_list[%d];\n", NumIvars);
166 printf("} _OBJC_INSTANCE_VARIABLES_%s "
167 "__attribute__ ((section (\"__OBJC, __instance_vars\")))= "
168 "{\n\t%d\n",IDecl->getName(),
169 NumIvars);
170 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
171 ? IDecl->getImplDeclIVars()
172 : CDecl->getIntfDeclIvars();
173 for (int i = 0; i < NumIvars; i++)
174 // TODO: 1) ivar names may have to go to another section. 2) encode
175 // ivar_type type of each ivar . 3) compute and add ivar offset.
176 printf("\t,\"%s\", \"\", 0\n", Ivars[i]->getName());
177 printf("};\n");
178 }
179
Fariborz Jahanian04455192007-10-22 21:41:37 +0000180 // Build _objc_method for class's instance or class methods metadata if needed
181 static bool objc_impl_method = false;
182 if (IDecl->getNumInstanceMethods() > 0 || IDecl->getNumClassMethods() > 0) {
183 if (!objc_impl_method) {
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000184 /* struct _objc_method {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000185 SEL _cmd;
186 char *method_types;
187 void *_imp;
188 }
189 */
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000190 printf("\nstruct _objc_method {\n");
191 printf("\tSEL _cmd;\n");
192 printf("\tchar *method_types;\n");
193 printf("\tvoid *_imp;\n");
194 printf("};\n");
Fariborz Jahanian04455192007-10-22 21:41:37 +0000195 objc_impl_method = true;
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000196 }
Fariborz Jahanian04455192007-10-22 21:41:37 +0000197 }
198 // Build _objc_method_list for class's instance methods if needed
199 if (IDecl->getNumInstanceMethods() > 0) {
200 int NumMethods = IDecl->getNumInstanceMethods();
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000201 /* struct _objc_method_list {
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000202 struct _objc_method_list *next_method;
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000203 int method_count;
204 struct _objc_method method_list[method_count];
205 }
206 */
207 printf("\nstatic struct {\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000208 printf("\tstruct _objc_method_list *next_method;\n");
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000209 printf("\tint method_count;\n");
210 printf("\tstruct _objc_method method_list[%d];\n", NumMethods);
211 printf("} _OBJC_INSTANCE_METHODS_%s "
212 "__attribute__ ((section (\"__OBJC, __inst_meth\")))= "
213 "{\n\t0, %d\n", IDecl->getName(), NumMethods);
214 ObjcMethodDecl **Methods = IDecl->getInstanceMethods();
215 for (int i = 0; i < NumMethods; i++)
216 // TODO: 1) method selector name may hav to go into their own section
217 // 2) encode method types for use here (which may have to go into
218 // __meth_var_types section, 3) Need method address as 3rd initializer.
219 printf("\t,(SEL)\"%s\", \"\", 0\n",
220 Methods[i]->getSelector().getName().c_str());
221 printf("};\n");
222 }
223
Fariborz Jahanian04455192007-10-22 21:41:37 +0000224 // Build _objc_method_list for class's class methods if needed
225 if (IDecl->getNumClassMethods() > 0) {
226 int NumMethods = IDecl->getNumClassMethods();
227 /* struct _objc_method_list {
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000228 struct _objc_method_list *next_method;
Fariborz Jahanian04455192007-10-22 21:41:37 +0000229 int method_count;
230 struct _objc_method method_list[method_count];
231 }
232 */
233 printf("\nstatic struct {\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000234 printf("\tstruct _objc_method_list *next_method;\n");
Fariborz Jahanian04455192007-10-22 21:41:37 +0000235 printf("\tint method_count;\n");
236 printf("\tstruct _objc_method method_list[%d];\n", NumMethods);
237 printf("} _OBJC_CLASS_METHODS_%s "
238 "__attribute__ ((section (\"__OBJC, __cls_meth\")))= "
239 "{\n\t0, %d\n", IDecl->getName(), NumMethods);
240 ObjcMethodDecl **Methods = IDecl->getClassMethods();
241 for (int i = 0; i < NumMethods; i++)
242 // TODO: 1) method selector name may hav to go into their own section
243 // 2) encode method types for use here (which may have to go into
244 // __meth_var_types section, 3) Need method address as 3rd initializer.
245 printf("\t,(SEL)\"%s\", \"\", 0\n",
246 Methods[i]->getSelector().getName().c_str());
247 printf("};\n");
248 }
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000249
Fariborz Jahanian04455192007-10-22 21:41:37 +0000250 // Protocols referenced in class declaration?
251 static bool objc_protocol_methods = false;
252 int NumProtocols = CDecl->getNumIntfRefProtocols();
253 if (NumProtocols > 0) {
254 ObjcProtocolDecl **Protocols = CDecl->getReferencedProtocols();
255 for (int i = 0; i < NumProtocols; i++) {
256 ObjcProtocolDecl *PDecl = Protocols[i];
257 // Output struct protocol_methods holder of method selector and type.
258 if (!objc_protocol_methods &&
259 (PDecl->getNumInstanceMethods() > 0
260 || PDecl->getNumClassMethods() > 0)) {
261 /* struct protocol_methods {
262 SEL _cmd;
263 char *method_types;
264 }
265 */
266 printf("\nstruct protocol_methods {\n");
267 printf("\tSEL _cmd;\n");
268 printf("\tchar *method_types;\n");
269 printf("};\n");
270 objc_protocol_methods = true;
271 }
272 // Output instance methods declared in this protocol.
273 /* struct _objc_protocol_method_list {
274 int protocol_method_count;
275 struct protocol_methods protocols[protocol_method_count];
276 }
277 */
278 int NumMethods = PDecl->getNumInstanceMethods();
279 if (NumMethods > 0) {
280 printf("\nstatic struct {\n");
281 printf("\tint protocol_method_count;\n");
282 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
283 printf("} _OBJC_PROTOCOL_INSTANCE_METHODS_%s "
284 "__attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
285 "{\n\t%d\n",PDecl->getName(), NumMethods);
286 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
287 for (int i = 0; i < NumMethods; i++)
288 // TODO: 1) method selector name may hav to go into their own section
289 // 2) encode method types for use here (which may have to go into
290 // __meth_var_types section.
291 printf("\t,(SEL)\"%s\", \"\"\n",
292 Methods[i]->getSelector().getName().c_str());
293 printf("};\n");
294 }
295
296 // Output class methods declared in this protocol.
297 NumMethods = PDecl->getNumClassMethods();
298 if (NumMethods > 0) {
299 printf("\nstatic struct {\n");
300 printf("\tint protocol_method_count;\n");
301 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
302 printf("} _OBJC_PROTOCOL_CLASS_METHODS_%s "
303 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
304 "{\n\t%d\n",PDecl->getName(), NumMethods);
305 ObjcMethodDecl **Methods = PDecl->getClassMethods();
306 for (int i = 0; i < NumMethods; i++)
307 // TODO: 1) method selector name may hav to go into their own section
308 // 2) encode method types for use here (which may have to go into
309 // __meth_var_types section.
310 printf("\t,(SEL)\"%s\", \"\"\n",
311 Methods[i]->getSelector().getName().c_str());
312 printf("};\n");
313 }
314 // Output:
315 /* struct _objc_protocol {
316 // Objective-C 1.0 extensions
317 struct _objc_protocol_extension *isa;
318 char *protocol_name;
319 struct _objc_protocol **protocol_list;
320 struct _objc__method_prototype_list *instance_methods;
321 struct _objc__method_prototype_list *class_methods;
322 };
323 */
324 static bool objc_protocol = false;
325 if (!objc_protocol) {
326 printf("\nstruct _objc_protocol {\n");
327 printf("\tstruct _objc_protocol_extension *isa;\n");
328 printf("\tchar *protocol_name;\n");
329 printf("\tstruct _objc_protocol **protocol_list;\n");
330 printf("\tstruct _objc__method_prototype_list *instance_methods;\n");
331 printf("\tstruct _objc__method_prototype_list *class_methods;\n");
332 printf("};\n");
333 objc_protocol = true;
334 }
335
336 printf("\nstatic struct _objc_protocol _OBJC_PROTOCOL_%s "
337 "__attribute__ ((section (\"__OBJC, __protocol\")))= "
338 "{\n\t0, \"%s\", 0, ", PDecl->getName(), PDecl->getName());
339 if (PDecl->getInstanceMethods() > 0)
340 printf("(struct _objc__method_prototype_list *)"
341 "&_OBJC_PROTOCOL_INSTANCE_METHODS_%s, ", PDecl->getName());
342 else
343 printf("0, ");
344 if (PDecl->getClassMethods() > 0)
345 printf("(struct _objc__method_prototype_list *)"
346 "&_OBJC_PROTOCOL_CLASS_METHODS_%s\n", PDecl->getName());
347 else
348 printf("0\n");
349 printf("};\n");
350 }
351 }
352 if (NumProtocols > 0) {
353 // Output the top lovel protocol meta-data for the class.
354 /* struct _objc_protocol_list {
355 struct _objc_protocol_list *next;
356 int protocol_count;
357 struct _objc_protocol *class_protocols[protocol_count];
358 }
359 */
360 printf("\nstatic struct {\n");
361 printf("\tstruct _objc_protocol_list *next;\n");
362 printf("\tint protocol_count;\n");
363 printf("\tstruct _objc_protocol *class_protocols[%d];\n"
364 "} _OBJC_CLASS_PROTOCOLS_%s "
365 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
366 "{\n\t0, %d\n",NumProtocols, CDecl->getName(), NumProtocols);
367 ObjcProtocolDecl **Protocols = CDecl->getReferencedProtocols();
368 for (int i = 0; i < NumProtocols; i++) {
369 ObjcProtocolDecl *PDecl = Protocols[i];
370 printf("\t,&_OBJC_PROTOCOL_%s \n",
371 PDecl->getName());
372 }
373 printf("};\n");
374 }
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000375
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000376 // Declaration of class/meta-class metadata
377 /* struct _objc_class {
378 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000379 const char *super_class_name;
380 char *name;
381 long version;
382 long info;
383 long instance_size;
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000384 struct _objc_ivar_list *ivars;
385 struct _objc_method_list *methods;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000386 struct objc_cache *cache;
387 struct objc_protocol_list *protocols;
388 const char *ivar_layout;
389 struct _objc_class_ext *ext;
390 };
391 */
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000392 static bool objc_class = false;
393 if (!objc_class) {
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000394 printf("\nstruct _objc_class {\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000395 printf("\tstruct _objc_class *isa;\n");
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000396 printf("\tconst char *super_class_name;\n");
397 printf("\tchar *name;\n");
398 printf("\tlong version;\n");
399 printf("\tlong info;\n");
400 printf("\tlong instance_size;\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000401 printf("\tstruct _objc_ivar_list *ivars;\n");
402 printf("\tstruct _objc_method_list *methods;\n");
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000403 printf("\tstruct objc_cache *cache;\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000404 printf("\tstruct _objc_protocol_list *protocols;\n");
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000405 printf("\tconst char *ivar_layout;\n");
406 printf("\tstruct _objc_class_ext *ext;\n");
407 printf("};\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000408 objc_class = true;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000409 }
410
411 // Meta-class metadata generation.
412 ObjcInterfaceDecl *RootClass = 0;
413 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
414 while (SuperClass) {
415 RootClass = SuperClass;
416 SuperClass = SuperClass->getSuperClass();
417 }
418 SuperClass = CDecl->getSuperClass();
419
420 printf("\nstatic struct _objc_class _OBJC_METACLASS_%s "
421 "__attribute__ ((section (\"__OBJC, __meta_class\")))= "
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000422 "{\n\t(struct _objc_class *)\"%s\"",
423 CDecl->getName(), RootClass ? RootClass->getName()
424 : CDecl->getName());
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000425 if (SuperClass)
426 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
427 else
428 printf(", 0, \"%s\"", CDecl->getName());
429 // FIXME: better way of getting size struct _objc_class (48)
430 // TODO: 'ivars' field for root class is currently set to 0.
431 // 'info' field is initialized to CLS_META(2) for metaclass
432 printf(", 0,2,48,0");
433 if (CDecl->getNumClassMethods() > 0)
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000434 printf("\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_%s\n",
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000435 CDecl->getName());
436 else
437 printf(", 0\n");
438 printf("\t,0,0,0,0\n");
439 printf("};\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000440
441 // class metadata generation.
442 printf("\nstatic struct _objc_class _OBJC_CLASS_%s "
443 "__attribute__ ((section (\"__OBJC, __class\")))= "
444 "{\n\t&_OBJC_METACLASS_%s", CDecl->getName(), CDecl->getName());
445 if (SuperClass)
446 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
447 else
448 printf(", 0, \"%s\"", CDecl->getName());
449 // 'info' field is initialized to CLS_CLASS(1) for class
450 // TODO: instance_size is curently set to 0.
451 printf(", 0,1,0");
452 if (NumIvars > 0)
453 printf(", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_%s\n\t",
454 CDecl->getName());
455 else
456 printf(",0");
457 if (IDecl->getNumInstanceMethods() > 0)
458 printf(", (struct _objc_method_list*)&_OBJC_INSTANCE_METHODS_%s, 0\n\t",
459 CDecl->getName());
460 else
461 printf(",0,0");
462 if (NumProtocols > 0)
463 printf(", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_%s, 0,0\n",
464 CDecl->getName());
465 else
466 printf(",0,0,0\n");
467 printf("};\n");
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000468}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000469
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000470void RewriteTest::WriteObjcMetaData() {
471 int ClsDefCount = ClassImplementation.size();
472 int CatDefCount = CategoryImplementation.size();
473 if (ClsDefCount == 0 && CatDefCount == 0)
474 return;
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000475
476 // For each defined class, write out all its meta data.
477 for (int i = 0; i < ClsDefCount; i++)
478 WriteObjcClassMetaData(ClassImplementation[i]);
479
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000480 // Write objc_symtab metadata
481 /*
482 struct _objc_symtab
483 {
484 long sel_ref_cnt;
485 SEL *refs;
486 short cls_def_cnt;
487 short cat_def_cnt;
488 void *defs[cls_def_cnt + cat_def_cnt];
489 };
490 */
491
492 printf("\nstruct _objc_symtab {\n");
493 printf("\tlong sel_ref_cnt;\n");
494 printf("\tSEL *refs;\n");
495 printf("\tshort cls_def_cnt;\n");
496 printf("\tshort cat_def_cnt;\n");
497 printf("\tvoid *defs[%d];\n", ClsDefCount + CatDefCount);
498 printf("};\n\n");
499
500 printf("static struct _objc_symtab "
501 "_OBJC_SYMBOLS __attribute__ ((section (\"__OBJC, __symbols\")))= {\n");
502 printf("\t0, 0, %d, %d\n", ClsDefCount, CatDefCount);
503 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000504 printf("\t,&_OBJC_CLASS_%s\n", ClassImplementation[i]->getName());
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000505
506 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000507 printf("\t,&_OBJC_CATEGORY_%s_%s\n",
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000508 CategoryImplementation[i]->getClassInterface()->getName(),
509 CategoryImplementation[i]->getName());
510
511 printf("};\n\n");
512
513 // Write objc_module metadata
514
515 /*
516 struct _objc_module {
517 long version;
518 long size;
519 const char *name;
520 struct _objc_symtab *symtab;
521 }
522 */
523
524 printf("\nstruct _objc_module {\n");
525 printf("\tlong version;\n");
526 printf("\tlong size;\n");
527 printf("\tconst char *name;\n");
528 printf("\tstruct _objc_symtab *symtab;");
529 printf("};\n\n");
530 printf("static struct _objc_module "
531 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n");
532 printf("\t%d, %d, \"\", &_OBJC_SYMBOLS\n", OBJC_ABI_VERSION, 16);
533 printf("};\n\n");
534}
Chris Lattner6fe8b272007-10-16 22:36:42 +0000535
Chris Lattner569faa62007-10-11 18:38:32 +0000536RewriteTest::~RewriteTest() {
Chris Lattner569faa62007-10-11 18:38:32 +0000537 // Get the top-level buffer that this corresponds to.
538 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
539 const char *MainBufStart = MainBuf.first;
540 const char *MainBufEnd = MainBuf.second;
541
542 // Loop over the whole file, looking for tabs.
543 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
544 if (*BufPtr != '\t')
545 continue;
546
547 // Okay, we found a tab. This tab will turn into at least one character,
548 // but it depends on which 'virtual column' it is in. Compute that now.
549 unsigned VCol = 0;
550 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
551 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
552 ++VCol;
553
554 // Okay, now that we know the virtual column, we know how many spaces to
555 // insert. We assume 8-character tab-stops.
556 unsigned Spaces = 8-(VCol & 7);
557
558 // Get the location of the tab.
559 SourceLocation TabLoc =
560 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
561
562 // Rewrite the single tab character into a sequence of spaces.
Chris Lattnere471a3b2007-10-13 00:46:29 +0000563 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
Chris Lattner569faa62007-10-11 18:38:32 +0000564 }
565
566 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
567 // we are done.
568 if (const RewriteBuffer *RewriteBuf =
569 Rewrite.getRewriteBufferFor(MainFileID)) {
Chris Lattner3cfe3d32007-10-13 00:11:23 +0000570 printf("Changed:\n");
571 std::string S(RewriteBuf->begin(), RewriteBuf->end());
572 printf("%s\n", S.c_str());
Chris Lattner569faa62007-10-11 18:38:32 +0000573 } else {
574 printf("No changes\n");
575 }
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000576 // Rewrite Objective-c meta data*
577 WriteObjcMetaData();
Chris Lattnerb429ae42007-10-11 00:43:27 +0000578}