blob: 42b5940e193c556eab43184d38ccd8ba014120a4 [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
22
23namespace {
Chris Lattner8a12c272007-10-11 18:38:32 +000024 class RewriteTest : public ASTConsumer {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000025 Rewriter Rewrite;
Chris Lattner01c57482007-10-17 22:35:30 +000026 ASTContext *Context;
Chris Lattner77cd2a02007-10-11 00:43:27 +000027 SourceManager *SM;
Chris Lattner8a12c272007-10-11 18:38:32 +000028 unsigned MainFileID;
Chris Lattner2c64b7b2007-10-16 21:07:07 +000029 SourceLocation LastIncLoc;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000030 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
31 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Steve Naroffebf2b562007-10-23 23:50:29 +000032
33 FunctionDecl *MsgSendFunctionDecl;
34 FunctionDecl *GetClassFunctionDecl;
35
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000036 static const int OBJC_ABI_VERSION =7 ;
Chris Lattner77cd2a02007-10-11 00:43:27 +000037 public:
Chris Lattner01c57482007-10-17 22:35:30 +000038 void Initialize(ASTContext &context, unsigned mainFileID) {
39 Context = &context;
40 SM = &Context->SourceMgr;
Chris Lattner8a12c272007-10-11 18:38:32 +000041 MainFileID = mainFileID;
Steve Naroffebf2b562007-10-23 23:50:29 +000042 MsgSendFunctionDecl = 0;
Chris Lattner01c57482007-10-17 22:35:30 +000043 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattner77cd2a02007-10-11 00:43:27 +000044 }
45
46 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner8a12c272007-10-11 18:38:32 +000047
Chris Lattner2c64b7b2007-10-16 21:07:07 +000048 void HandleDeclInMainFile(Decl *D);
49 void RewriteInclude(SourceLocation Loc);
Chris Lattner311ff022007-10-16 22:36:42 +000050
51 void RewriteFunctionBody(Stmt *S);
52 void RewriteAtEncode(ObjCEncodeExpr *Exp);
Steve Naroff7e158912007-10-23 20:20:08 +000053 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Steve Naroffebf2b562007-10-23 23:50:29 +000054 void RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroff7e158912007-10-23 20:20:08 +000055
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +000056 void WriteObjcClassMetaData(ObjcImplementationDecl *IDecl);
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000057 void WriteObjcMetaData();
58
Chris Lattner8a12c272007-10-11 18:38:32 +000059 ~RewriteTest();
Chris Lattner77cd2a02007-10-11 00:43:27 +000060 };
61}
62
Chris Lattner8a12c272007-10-11 18:38:32 +000063ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattner77cd2a02007-10-11 00:43:27 +000064
Chris Lattner8a12c272007-10-11 18:38:32 +000065void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000066 // Two cases: either the decl could be in the main file, or it could be in a
67 // #included file. If the former, rewrite it now. If the later, check to see
68 // if we rewrote the #include/#import.
69 SourceLocation Loc = D->getLocation();
70 Loc = SM->getLogicalLoc(Loc);
71
72 // If this is for a builtin, ignore it.
73 if (Loc.isInvalid()) return;
74
Steve Naroffebf2b562007-10-23 23:50:29 +000075 // Look for built-in declarations that we need to refer during the rewrite.
76 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
77 if (FD->getIdentifier() == &Context->Idents.get("objc_msgSend"))
78 MsgSendFunctionDecl = FD;
79 else if (FD->getIdentifier() == &Context->Idents.get("objc_getClass"))
80 GetClassFunctionDecl = FD;
81 }
Chris Lattner2c64b7b2007-10-16 21:07:07 +000082 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
83 return HandleDeclInMainFile(D);
84
85 RewriteInclude(Loc);
86}
87
88void RewriteTest::RewriteInclude(SourceLocation Loc) {
89 // Rip up the #include stack to the main file.
90 SourceLocation IncLoc = Loc, NextLoc = Loc;
91 do {
92 IncLoc = Loc;
93 Loc = SM->getLogicalLoc(NextLoc);
94 NextLoc = SM->getIncludeLoc(Loc);
95 } while (!NextLoc.isInvalid());
96
97 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
98 // IncLoc indicates the header that was included if it is useful.
99 IncLoc = SM->getLogicalLoc(IncLoc);
100 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
101 Loc == LastIncLoc)
102 return;
103 LastIncLoc = Loc;
104
105 unsigned IncCol = SM->getColumnNumber(Loc);
106 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
107
108 // Replace the #import with #include.
109 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
110}
111
112/// HandleDeclInMainFile - This is called for each top-level decl defined in the
113/// main file of the input.
114void RewriteTest::HandleDeclInMainFile(Decl *D) {
Chris Lattner311ff022007-10-16 22:36:42 +0000115 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
116 if (Stmt *Body = FD->getBody())
117 RewriteFunctionBody(Body);
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000118
119 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
120 ClassImplementation.push_back(CI);
121 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
122 CategoryImplementation.push_back(CI);
Steve Naroff7e158912007-10-23 20:20:08 +0000123 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
124 RewriteForwardClassDecl(CD);
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000125 // Nothing yet.
Chris Lattner8a12c272007-10-11 18:38:32 +0000126}
127
128
Chris Lattner311ff022007-10-16 22:36:42 +0000129void RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner311ff022007-10-16 22:36:42 +0000130 // Otherwise, just rewrite all children.
131 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
132 CI != E; ++CI)
Chris Lattner50754772007-10-17 21:28:00 +0000133 if (*CI)
134 RewriteFunctionBody(*CI);
Steve Naroffebf2b562007-10-23 23:50:29 +0000135
136 // Handle specific things.
137 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
138 return RewriteAtEncode(AtEncode);
139
140 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S))
141 return RewriteMessageExpr(MessExpr);
142
Chris Lattner311ff022007-10-16 22:36:42 +0000143}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000144
Chris Lattner311ff022007-10-16 22:36:42 +0000145void RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattner01c57482007-10-17 22:35:30 +0000146 // Create a new string expression.
147 QualType StrType = Context->getPointerType(Context->CharTy);
148 Expr *Replacement = new StringLiteral("foo", 3, false, StrType,
149 SourceLocation(), SourceLocation());
150 Rewrite.ReplaceStmt(Exp, Replacement);
151 delete Replacement;
Chris Lattner311ff022007-10-16 22:36:42 +0000152}
153
Steve Naroffebf2b562007-10-23 23:50:29 +0000154
155void RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
156 assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
157 //Exp->dumpPretty();
158 //printf("\n");
159
160 // Synthesize a call to objc_msgSend().
161
162 // Get the type, we will need to reference it in a couple spots.
163 QualType msgSendType = MsgSendFunctionDecl->getType();
164
165 // Create a reference to the objc_msgSend() declaration.
166 DeclRefExpr *DRE = new DeclRefExpr(MsgSendFunctionDecl, msgSendType,
167 SourceLocation());
168
169 // Now, we cast the reference to a pointer to the objc_msgSend type.
170 QualType pToFunc = Context->getPointerType(msgSendType);
171 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
172
173 const FunctionType *FT = msgSendType->getAsFunctionType();
174 CallExpr *CE = new CallExpr(ICE, 0, 0, FT->getResultType(),
175 SourceLocation());
176 Rewrite.ReplaceStmt(Exp, CE);
177 //Exp->dump();
178 //CE->dump();
179}
180
Steve Naroff7e158912007-10-23 20:20:08 +0000181void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
182 int numDecls = ClassDecl->getNumForwardDecls();
183 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
184
185 // Get the start location and compute the semi location.
186 SourceLocation startLoc = ClassDecl->getLocation();
187 const char *startBuf = SM->getCharacterData(startLoc);
188 const char *semiPtr = startBuf;
189 while (semiPtr && (*semiPtr != ';')) semiPtr++;
190
191 // Translate to typedef's that forward reference structs with the same name
192 // as the class. As a convenience, we include the original declaration
193 // as a comment.
194 std::string typedefString;
195 typedefString += "// ";
196 typedefString.append(startBuf, semiPtr-startBuf+1);
197 typedefString += "\n";
198 for (int i = 0; i < numDecls; i++) {
199 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
200 typedefString += "typedef struct ";
201 typedefString += ForwardDecl->getName();
202 typedefString += " ";
203 typedefString += ForwardDecl->getName();
204 typedefString += ";\n";
205 }
206
207 // Replace the @class with typedefs corresponding to the classes.
208 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
209 typedefString.c_str(), typedefString.size());
210}
211
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000212void RewriteTest::WriteObjcClassMetaData(ObjcImplementationDecl *IDecl) {
213 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
214
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000215 // Build _objc_ivar_list metadata for classes ivars if needed
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000216 int NumIvars = IDecl->getImplDeclNumIvars() > 0
217 ? IDecl->getImplDeclNumIvars()
218 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
219
220 if (NumIvars > 0) {
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000221 static bool objc_ivar = false;
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000222 if (!objc_ivar) {
223 /* struct _objc_ivar {
224 char *ivar_name;
225 char *ivar_type;
226 int ivar_offset;
227 };
228 */
229 printf("\nstruct _objc_ivar {\n");
230 printf("\tchar *ivar_name;\n");
231 printf("\tchar *ivar_type;\n");
232 printf("\tint ivar_offset;\n");
233 printf("};\n");
234 objc_ivar = true;
235 }
236
237 /* struct _objc_ivar_list {
238 int ivar_count;
239 struct _objc_ivar ivar_list[ivar_count];
240 };
241 */
242 printf("\nstatic struct {\n");
243 printf("\tint ivar_count;\n");
244 printf("\tstruct _objc_ivar ivar_list[%d];\n", NumIvars);
245 printf("} _OBJC_INSTANCE_VARIABLES_%s "
246 "__attribute__ ((section (\"__OBJC, __instance_vars\")))= "
247 "{\n\t%d\n",IDecl->getName(),
248 NumIvars);
249 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
250 ? IDecl->getImplDeclIVars()
251 : CDecl->getIntfDeclIvars();
252 for (int i = 0; i < NumIvars; i++)
253 // TODO: 1) ivar names may have to go to another section. 2) encode
254 // ivar_type type of each ivar . 3) compute and add ivar offset.
255 printf("\t,\"%s\", \"\", 0\n", Ivars[i]->getName());
256 printf("};\n");
257 }
258
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000259 // Build _objc_method for class's instance or class methods metadata if needed
260 static bool objc_impl_method = false;
261 if (IDecl->getNumInstanceMethods() > 0 || IDecl->getNumClassMethods() > 0) {
262 if (!objc_impl_method) {
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000263 /* struct _objc_method {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000264 SEL _cmd;
265 char *method_types;
266 void *_imp;
267 }
268 */
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000269 printf("\nstruct _objc_method {\n");
270 printf("\tSEL _cmd;\n");
271 printf("\tchar *method_types;\n");
272 printf("\tvoid *_imp;\n");
273 printf("};\n");
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000274 objc_impl_method = true;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000275 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000276 }
277 // Build _objc_method_list for class's instance methods if needed
278 if (IDecl->getNumInstanceMethods() > 0) {
279 int NumMethods = IDecl->getNumInstanceMethods();
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000280 /* struct _objc_method_list {
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000281 struct _objc_method_list *next_method;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000282 int method_count;
283 struct _objc_method method_list[method_count];
284 }
285 */
286 printf("\nstatic struct {\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000287 printf("\tstruct _objc_method_list *next_method;\n");
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000288 printf("\tint method_count;\n");
289 printf("\tstruct _objc_method method_list[%d];\n", NumMethods);
290 printf("} _OBJC_INSTANCE_METHODS_%s "
291 "__attribute__ ((section (\"__OBJC, __inst_meth\")))= "
292 "{\n\t0, %d\n", IDecl->getName(), NumMethods);
293 ObjcMethodDecl **Methods = IDecl->getInstanceMethods();
294 for (int i = 0; i < NumMethods; i++)
295 // TODO: 1) method selector name may hav to go into their own section
296 // 2) encode method types for use here (which may have to go into
297 // __meth_var_types section, 3) Need method address as 3rd initializer.
298 printf("\t,(SEL)\"%s\", \"\", 0\n",
299 Methods[i]->getSelector().getName().c_str());
300 printf("};\n");
301 }
302
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000303 // Build _objc_method_list for class's class methods if needed
304 if (IDecl->getNumClassMethods() > 0) {
305 int NumMethods = IDecl->getNumClassMethods();
306 /* struct _objc_method_list {
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000307 struct _objc_method_list *next_method;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000308 int method_count;
309 struct _objc_method method_list[method_count];
310 }
311 */
312 printf("\nstatic struct {\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000313 printf("\tstruct _objc_method_list *next_method;\n");
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000314 printf("\tint method_count;\n");
315 printf("\tstruct _objc_method method_list[%d];\n", NumMethods);
316 printf("} _OBJC_CLASS_METHODS_%s "
317 "__attribute__ ((section (\"__OBJC, __cls_meth\")))= "
318 "{\n\t0, %d\n", IDecl->getName(), NumMethods);
319 ObjcMethodDecl **Methods = IDecl->getClassMethods();
320 for (int i = 0; i < NumMethods; i++)
321 // TODO: 1) method selector name may hav to go into their own section
322 // 2) encode method types for use here (which may have to go into
323 // __meth_var_types section, 3) Need method address as 3rd initializer.
324 printf("\t,(SEL)\"%s\", \"\", 0\n",
325 Methods[i]->getSelector().getName().c_str());
326 printf("};\n");
327 }
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000328
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000329 // Protocols referenced in class declaration?
330 static bool objc_protocol_methods = false;
331 int NumProtocols = CDecl->getNumIntfRefProtocols();
332 if (NumProtocols > 0) {
333 ObjcProtocolDecl **Protocols = CDecl->getReferencedProtocols();
334 for (int i = 0; i < NumProtocols; i++) {
335 ObjcProtocolDecl *PDecl = Protocols[i];
336 // Output struct protocol_methods holder of method selector and type.
337 if (!objc_protocol_methods &&
338 (PDecl->getNumInstanceMethods() > 0
339 || PDecl->getNumClassMethods() > 0)) {
340 /* struct protocol_methods {
341 SEL _cmd;
342 char *method_types;
343 }
344 */
345 printf("\nstruct protocol_methods {\n");
346 printf("\tSEL _cmd;\n");
347 printf("\tchar *method_types;\n");
348 printf("};\n");
349 objc_protocol_methods = true;
350 }
351 // Output instance methods declared in this protocol.
352 /* struct _objc_protocol_method_list {
353 int protocol_method_count;
354 struct protocol_methods protocols[protocol_method_count];
355 }
356 */
357 int NumMethods = PDecl->getNumInstanceMethods();
358 if (NumMethods > 0) {
359 printf("\nstatic struct {\n");
360 printf("\tint protocol_method_count;\n");
361 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
362 printf("} _OBJC_PROTOCOL_INSTANCE_METHODS_%s "
363 "__attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
364 "{\n\t%d\n",PDecl->getName(), NumMethods);
365 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
366 for (int i = 0; i < NumMethods; i++)
367 // TODO: 1) method selector name may hav to go into their own section
368 // 2) encode method types for use here (which may have to go into
369 // __meth_var_types section.
370 printf("\t,(SEL)\"%s\", \"\"\n",
371 Methods[i]->getSelector().getName().c_str());
372 printf("};\n");
373 }
374
375 // Output class methods declared in this protocol.
376 NumMethods = PDecl->getNumClassMethods();
377 if (NumMethods > 0) {
378 printf("\nstatic struct {\n");
379 printf("\tint protocol_method_count;\n");
380 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
381 printf("} _OBJC_PROTOCOL_CLASS_METHODS_%s "
382 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
383 "{\n\t%d\n",PDecl->getName(), NumMethods);
384 ObjcMethodDecl **Methods = PDecl->getClassMethods();
385 for (int i = 0; i < NumMethods; i++)
386 // TODO: 1) method selector name may hav to go into their own section
387 // 2) encode method types for use here (which may have to go into
388 // __meth_var_types section.
389 printf("\t,(SEL)\"%s\", \"\"\n",
390 Methods[i]->getSelector().getName().c_str());
391 printf("};\n");
392 }
393 // Output:
394 /* struct _objc_protocol {
395 // Objective-C 1.0 extensions
396 struct _objc_protocol_extension *isa;
397 char *protocol_name;
398 struct _objc_protocol **protocol_list;
399 struct _objc__method_prototype_list *instance_methods;
400 struct _objc__method_prototype_list *class_methods;
401 };
402 */
403 static bool objc_protocol = false;
404 if (!objc_protocol) {
405 printf("\nstruct _objc_protocol {\n");
406 printf("\tstruct _objc_protocol_extension *isa;\n");
407 printf("\tchar *protocol_name;\n");
408 printf("\tstruct _objc_protocol **protocol_list;\n");
409 printf("\tstruct _objc__method_prototype_list *instance_methods;\n");
410 printf("\tstruct _objc__method_prototype_list *class_methods;\n");
411 printf("};\n");
412 objc_protocol = true;
413 }
414
415 printf("\nstatic struct _objc_protocol _OBJC_PROTOCOL_%s "
416 "__attribute__ ((section (\"__OBJC, __protocol\")))= "
417 "{\n\t0, \"%s\", 0, ", PDecl->getName(), PDecl->getName());
418 if (PDecl->getInstanceMethods() > 0)
419 printf("(struct _objc__method_prototype_list *)"
420 "&_OBJC_PROTOCOL_INSTANCE_METHODS_%s, ", PDecl->getName());
421 else
422 printf("0, ");
423 if (PDecl->getClassMethods() > 0)
424 printf("(struct _objc__method_prototype_list *)"
425 "&_OBJC_PROTOCOL_CLASS_METHODS_%s\n", PDecl->getName());
426 else
427 printf("0\n");
428 printf("};\n");
429 }
430 }
431 if (NumProtocols > 0) {
432 // Output the top lovel protocol meta-data for the class.
433 /* struct _objc_protocol_list {
434 struct _objc_protocol_list *next;
435 int protocol_count;
436 struct _objc_protocol *class_protocols[protocol_count];
437 }
438 */
439 printf("\nstatic struct {\n");
440 printf("\tstruct _objc_protocol_list *next;\n");
441 printf("\tint protocol_count;\n");
442 printf("\tstruct _objc_protocol *class_protocols[%d];\n"
443 "} _OBJC_CLASS_PROTOCOLS_%s "
444 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
445 "{\n\t0, %d\n",NumProtocols, CDecl->getName(), NumProtocols);
446 ObjcProtocolDecl **Protocols = CDecl->getReferencedProtocols();
447 for (int i = 0; i < NumProtocols; i++) {
448 ObjcProtocolDecl *PDecl = Protocols[i];
449 printf("\t,&_OBJC_PROTOCOL_%s \n",
450 PDecl->getName());
451 }
452 printf("};\n");
453 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000454
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000455 // Declaration of class/meta-class metadata
456 /* struct _objc_class {
457 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000458 const char *super_class_name;
459 char *name;
460 long version;
461 long info;
462 long instance_size;
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000463 struct _objc_ivar_list *ivars;
464 struct _objc_method_list *methods;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000465 struct objc_cache *cache;
466 struct objc_protocol_list *protocols;
467 const char *ivar_layout;
468 struct _objc_class_ext *ext;
469 };
470 */
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000471 static bool objc_class = false;
472 if (!objc_class) {
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000473 printf("\nstruct _objc_class {\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000474 printf("\tstruct _objc_class *isa;\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000475 printf("\tconst char *super_class_name;\n");
476 printf("\tchar *name;\n");
477 printf("\tlong version;\n");
478 printf("\tlong info;\n");
479 printf("\tlong instance_size;\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000480 printf("\tstruct _objc_ivar_list *ivars;\n");
481 printf("\tstruct _objc_method_list *methods;\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000482 printf("\tstruct objc_cache *cache;\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000483 printf("\tstruct _objc_protocol_list *protocols;\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000484 printf("\tconst char *ivar_layout;\n");
485 printf("\tstruct _objc_class_ext *ext;\n");
486 printf("};\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000487 objc_class = true;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000488 }
489
490 // Meta-class metadata generation.
491 ObjcInterfaceDecl *RootClass = 0;
492 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
493 while (SuperClass) {
494 RootClass = SuperClass;
495 SuperClass = SuperClass->getSuperClass();
496 }
497 SuperClass = CDecl->getSuperClass();
498
499 printf("\nstatic struct _objc_class _OBJC_METACLASS_%s "
500 "__attribute__ ((section (\"__OBJC, __meta_class\")))= "
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000501 "{\n\t(struct _objc_class *)\"%s\"",
502 CDecl->getName(), RootClass ? RootClass->getName()
503 : CDecl->getName());
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000504 if (SuperClass)
505 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
506 else
507 printf(", 0, \"%s\"", CDecl->getName());
508 // FIXME: better way of getting size struct _objc_class (48)
509 // TODO: 'ivars' field for root class is currently set to 0.
510 // 'info' field is initialized to CLS_META(2) for metaclass
511 printf(", 0,2,48,0");
512 if (CDecl->getNumClassMethods() > 0)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000513 printf("\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_%s\n",
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000514 CDecl->getName());
515 else
516 printf(", 0\n");
517 printf("\t,0,0,0,0\n");
518 printf("};\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000519
520 // class metadata generation.
521 printf("\nstatic struct _objc_class _OBJC_CLASS_%s "
522 "__attribute__ ((section (\"__OBJC, __class\")))= "
523 "{\n\t&_OBJC_METACLASS_%s", CDecl->getName(), CDecl->getName());
524 if (SuperClass)
525 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
526 else
527 printf(", 0, \"%s\"", CDecl->getName());
528 // 'info' field is initialized to CLS_CLASS(1) for class
529 // TODO: instance_size is curently set to 0.
530 printf(", 0,1,0");
531 if (NumIvars > 0)
532 printf(", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_%s\n\t",
533 CDecl->getName());
534 else
535 printf(",0");
536 if (IDecl->getNumInstanceMethods() > 0)
537 printf(", (struct _objc_method_list*)&_OBJC_INSTANCE_METHODS_%s, 0\n\t",
538 CDecl->getName());
539 else
540 printf(",0,0");
541 if (NumProtocols > 0)
542 printf(", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_%s, 0,0\n",
543 CDecl->getName());
544 else
545 printf(",0,0,0\n");
546 printf("};\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000547}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000548
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000549void RewriteTest::WriteObjcMetaData() {
550 int ClsDefCount = ClassImplementation.size();
551 int CatDefCount = CategoryImplementation.size();
552 if (ClsDefCount == 0 && CatDefCount == 0)
553 return;
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000554
555 // For each defined class, write out all its meta data.
556 for (int i = 0; i < ClsDefCount; i++)
557 WriteObjcClassMetaData(ClassImplementation[i]);
558
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000559 // Write objc_symtab metadata
560 /*
561 struct _objc_symtab
562 {
563 long sel_ref_cnt;
564 SEL *refs;
565 short cls_def_cnt;
566 short cat_def_cnt;
567 void *defs[cls_def_cnt + cat_def_cnt];
568 };
569 */
570
571 printf("\nstruct _objc_symtab {\n");
572 printf("\tlong sel_ref_cnt;\n");
573 printf("\tSEL *refs;\n");
574 printf("\tshort cls_def_cnt;\n");
575 printf("\tshort cat_def_cnt;\n");
576 printf("\tvoid *defs[%d];\n", ClsDefCount + CatDefCount);
577 printf("};\n\n");
578
579 printf("static struct _objc_symtab "
580 "_OBJC_SYMBOLS __attribute__ ((section (\"__OBJC, __symbols\")))= {\n");
581 printf("\t0, 0, %d, %d\n", ClsDefCount, CatDefCount);
582 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000583 printf("\t,&_OBJC_CLASS_%s\n", ClassImplementation[i]->getName());
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000584
585 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000586 printf("\t,&_OBJC_CATEGORY_%s_%s\n",
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000587 CategoryImplementation[i]->getClassInterface()->getName(),
588 CategoryImplementation[i]->getName());
589
590 printf("};\n\n");
591
592 // Write objc_module metadata
593
594 /*
595 struct _objc_module {
596 long version;
597 long size;
598 const char *name;
599 struct _objc_symtab *symtab;
600 }
601 */
602
603 printf("\nstruct _objc_module {\n");
604 printf("\tlong version;\n");
605 printf("\tlong size;\n");
606 printf("\tconst char *name;\n");
607 printf("\tstruct _objc_symtab *symtab;");
608 printf("};\n\n");
609 printf("static struct _objc_module "
610 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n");
611 printf("\t%d, %d, \"\", &_OBJC_SYMBOLS\n", OBJC_ABI_VERSION, 16);
612 printf("};\n\n");
613}
Chris Lattner311ff022007-10-16 22:36:42 +0000614
Chris Lattner8a12c272007-10-11 18:38:32 +0000615RewriteTest::~RewriteTest() {
Chris Lattner8a12c272007-10-11 18:38:32 +0000616 // Get the top-level buffer that this corresponds to.
617 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
618 const char *MainBufStart = MainBuf.first;
619 const char *MainBufEnd = MainBuf.second;
620
621 // Loop over the whole file, looking for tabs.
622 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
623 if (*BufPtr != '\t')
624 continue;
625
626 // Okay, we found a tab. This tab will turn into at least one character,
627 // but it depends on which 'virtual column' it is in. Compute that now.
628 unsigned VCol = 0;
629 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
630 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
631 ++VCol;
632
633 // Okay, now that we know the virtual column, we know how many spaces to
634 // insert. We assume 8-character tab-stops.
635 unsigned Spaces = 8-(VCol & 7);
636
637 // Get the location of the tab.
638 SourceLocation TabLoc =
639 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
640
641 // Rewrite the single tab character into a sequence of spaces.
Chris Lattner57c337d2007-10-13 00:46:29 +0000642 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
Chris Lattner8a12c272007-10-11 18:38:32 +0000643 }
644
645 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
646 // we are done.
647 if (const RewriteBuffer *RewriteBuf =
648 Rewrite.getRewriteBufferFor(MainFileID)) {
Chris Lattner7c239602007-10-13 00:11:23 +0000649 printf("Changed:\n");
650 std::string S(RewriteBuf->begin(), RewriteBuf->end());
651 printf("%s\n", S.c_str());
Chris Lattner8a12c272007-10-11 18:38:32 +0000652 } else {
653 printf("No changes\n");
654 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000655 // Rewrite Objective-c meta data*
656 WriteObjcMetaData();
Chris Lattner77cd2a02007-10-11 00:43:27 +0000657}