blob: afe9493068bbd3ac4a191b06251d5ef4dcf7b37a [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 Lattner158ecb92007-10-25 17:07:24 +000020#include "llvm/ADT/StringExtras.h"
Chris Lattner77cd2a02007-10-11 00:43:27 +000021using namespace clang;
Chris Lattner158ecb92007-10-25 17:07:24 +000022using llvm::utostr;
Chris Lattner77cd2a02007-10-11 00:43:27 +000023
Chris Lattner77cd2a02007-10-11 00:43:27 +000024namespace {
Chris Lattner8a12c272007-10-11 18:38:32 +000025 class RewriteTest : public ASTConsumer {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000026 Rewriter Rewrite;
Chris Lattner01c57482007-10-17 22:35:30 +000027 ASTContext *Context;
Chris Lattner77cd2a02007-10-11 00:43:27 +000028 SourceManager *SM;
Chris Lattner8a12c272007-10-11 18:38:32 +000029 unsigned MainFileID;
Chris Lattner2c64b7b2007-10-16 21:07:07 +000030 SourceLocation LastIncLoc;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000031 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
32 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Steve Naroffebf2b562007-10-23 23:50:29 +000033
34 FunctionDecl *MsgSendFunctionDecl;
35 FunctionDecl *GetClassFunctionDecl;
Steve Naroff934f2762007-10-24 22:48:43 +000036 FunctionDecl *SelGetUidFunctionDecl;
Steve Naroffebf2b562007-10-23 23:50:29 +000037
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000038 static const int OBJC_ABI_VERSION =7 ;
Chris Lattner77cd2a02007-10-11 00:43:27 +000039 public:
Chris Lattner01c57482007-10-17 22:35:30 +000040 void Initialize(ASTContext &context, unsigned mainFileID) {
41 Context = &context;
42 SM = &Context->SourceMgr;
Chris Lattner8a12c272007-10-11 18:38:32 +000043 MainFileID = mainFileID;
Steve Naroffebf2b562007-10-23 23:50:29 +000044 MsgSendFunctionDecl = 0;
Steve Naroffc0006092007-10-24 01:09:48 +000045 GetClassFunctionDecl = 0;
Steve Naroff934f2762007-10-24 22:48:43 +000046 SelGetUidFunctionDecl = 0;
Chris Lattner01c57482007-10-17 22:35:30 +000047 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattner77cd2a02007-10-11 00:43:27 +000048 }
Chris Lattner8a12c272007-10-11 18:38:32 +000049
Chris Lattnerf04da132007-10-24 17:06:59 +000050 // Top Level Driver code.
51 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner2c64b7b2007-10-16 21:07:07 +000052 void HandleDeclInMainFile(Decl *D);
Chris Lattnerf04da132007-10-24 17:06:59 +000053 ~RewriteTest();
54
55 // Syntactic Rewriting.
Chris Lattner2c64b7b2007-10-16 21:07:07 +000056 void RewriteInclude(SourceLocation Loc);
Chris Lattnerf04da132007-10-24 17:06:59 +000057 void RewriteTabs();
58 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Chris Lattner311ff022007-10-16 22:36:42 +000059
Chris Lattnerf04da132007-10-24 17:06:59 +000060 // Expression Rewriting.
Chris Lattnere64b7772007-10-24 16:57:36 +000061 Stmt *RewriteFunctionBody(Stmt *S);
62 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
63 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroff934f2762007-10-24 22:48:43 +000064 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
65 Expr **args, unsigned nargs);
Chris Lattnerf04da132007-10-24 17:06:59 +000066 // Metadata emission.
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000067 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl);
68
69 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl);
70
71 void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
72 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +000073 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000074 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +000075 const char *ClassName,
76 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000077
78 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
79 int NumProtocols,
80 const char *prefix,
81 const char *ClassName);
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000082 void WriteObjcMetaData();
Chris Lattner77cd2a02007-10-11 00:43:27 +000083 };
84}
85
Chris Lattner8a12c272007-10-11 18:38:32 +000086ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattner77cd2a02007-10-11 00:43:27 +000087
Chris Lattnerf04da132007-10-24 17:06:59 +000088//===----------------------------------------------------------------------===//
89// Top Level Driver Code
90//===----------------------------------------------------------------------===//
91
Chris Lattner8a12c272007-10-11 18:38:32 +000092void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000093 // Two cases: either the decl could be in the main file, or it could be in a
94 // #included file. If the former, rewrite it now. If the later, check to see
95 // if we rewrote the #include/#import.
96 SourceLocation Loc = D->getLocation();
97 Loc = SM->getLogicalLoc(Loc);
98
99 // If this is for a builtin, ignore it.
100 if (Loc.isInvalid()) return;
101
Steve Naroffebf2b562007-10-23 23:50:29 +0000102 // Look for built-in declarations that we need to refer during the rewrite.
103 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroffc0006092007-10-24 01:09:48 +0000104 if (strcmp(FD->getName(), "objc_msgSend") == 0)
Steve Naroffebf2b562007-10-23 23:50:29 +0000105 MsgSendFunctionDecl = FD;
Steve Naroffc0006092007-10-24 01:09:48 +0000106 else if (strcmp(FD->getName(), "objc_getClass") == 0)
Steve Naroffebf2b562007-10-23 23:50:29 +0000107 GetClassFunctionDecl = FD;
Steve Naroff934f2762007-10-24 22:48:43 +0000108 else if (strcmp(FD->getName(), "sel_getUid") == 0)
109 SelGetUidFunctionDecl = FD;
Steve Naroffebf2b562007-10-23 23:50:29 +0000110 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000111
112 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000113 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
114 return HandleDeclInMainFile(D);
115
Chris Lattnerf04da132007-10-24 17:06:59 +0000116 // Otherwise, see if there is a #import in the main file that should be
117 // rewritten.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000118 RewriteInclude(Loc);
119}
120
Chris Lattnerf04da132007-10-24 17:06:59 +0000121/// HandleDeclInMainFile - This is called for each top-level decl defined in the
122/// main file of the input.
123void RewriteTest::HandleDeclInMainFile(Decl *D) {
124 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
125 if (Stmt *Body = FD->getBody())
126 FD->setBody(RewriteFunctionBody(Body));
127
128 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
129 ClassImplementation.push_back(CI);
130 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
131 CategoryImplementation.push_back(CI);
132 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
133 RewriteForwardClassDecl(CD);
134 // Nothing yet.
135}
136
137RewriteTest::~RewriteTest() {
138 // Get the top-level buffer that this corresponds to.
139 RewriteTabs();
140
141 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
142 // we are done.
143 if (const RewriteBuffer *RewriteBuf =
144 Rewrite.getRewriteBufferFor(MainFileID)) {
145 printf("Changed:\n");
146 std::string S(RewriteBuf->begin(), RewriteBuf->end());
147 printf("%s\n", S.c_str());
148 } else {
149 printf("No changes\n");
150 }
151
152 // Rewrite Objective-c meta data*
153 WriteObjcMetaData();
154}
155
156//===----------------------------------------------------------------------===//
157// Syntactic (non-AST) Rewriting Code
158//===----------------------------------------------------------------------===//
159
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000160void RewriteTest::RewriteInclude(SourceLocation Loc) {
161 // Rip up the #include stack to the main file.
162 SourceLocation IncLoc = Loc, NextLoc = Loc;
163 do {
164 IncLoc = Loc;
165 Loc = SM->getLogicalLoc(NextLoc);
166 NextLoc = SM->getIncludeLoc(Loc);
167 } while (!NextLoc.isInvalid());
168
169 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
170 // IncLoc indicates the header that was included if it is useful.
171 IncLoc = SM->getLogicalLoc(IncLoc);
172 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
173 Loc == LastIncLoc)
174 return;
175 LastIncLoc = Loc;
176
177 unsigned IncCol = SM->getColumnNumber(Loc);
178 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
179
180 // Replace the #import with #include.
181 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
182}
183
Chris Lattnerf04da132007-10-24 17:06:59 +0000184void RewriteTest::RewriteTabs() {
185 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
186 const char *MainBufStart = MainBuf.first;
187 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000188
Chris Lattnerf04da132007-10-24 17:06:59 +0000189 // Loop over the whole file, looking for tabs.
190 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
191 if (*BufPtr != '\t')
192 continue;
193
194 // Okay, we found a tab. This tab will turn into at least one character,
195 // but it depends on which 'virtual column' it is in. Compute that now.
196 unsigned VCol = 0;
197 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
198 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
199 ++VCol;
200
201 // Okay, now that we know the virtual column, we know how many spaces to
202 // insert. We assume 8-character tab-stops.
203 unsigned Spaces = 8-(VCol & 7);
204
205 // Get the location of the tab.
206 SourceLocation TabLoc =
207 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
208
209 // Rewrite the single tab character into a sequence of spaces.
210 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
211 }
Chris Lattner8a12c272007-10-11 18:38:32 +0000212}
213
214
Chris Lattnerf04da132007-10-24 17:06:59 +0000215void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
216 int numDecls = ClassDecl->getNumForwardDecls();
217 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
218
219 // Get the start location and compute the semi location.
220 SourceLocation startLoc = ClassDecl->getLocation();
221 const char *startBuf = SM->getCharacterData(startLoc);
222 const char *semiPtr = strchr(startBuf, ';');
223
224 // Translate to typedef's that forward reference structs with the same name
225 // as the class. As a convenience, we include the original declaration
226 // as a comment.
227 std::string typedefString;
228 typedefString += "// ";
Steve Naroff934f2762007-10-24 22:48:43 +0000229 typedefString.append(startBuf, semiPtr-startBuf+1);
230 typedefString += "\n";
231 for (int i = 0; i < numDecls; i++) {
232 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
233 typedefString += "typedef struct ";
234 typedefString += ForwardDecl->getName();
235 typedefString += " ";
236 typedefString += ForwardDecl->getName();
237 typedefString += ";\n";
238 }
239
240 // Replace the @class with typedefs corresponding to the classes.
241 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
242 typedefString.c_str(), typedefString.size());
Chris Lattnerf04da132007-10-24 17:06:59 +0000243}
244
245//===----------------------------------------------------------------------===//
246// Function Body / Expression rewriting
247//===----------------------------------------------------------------------===//
248
Chris Lattnere64b7772007-10-24 16:57:36 +0000249Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner311ff022007-10-16 22:36:42 +0000250 // Otherwise, just rewrite all children.
251 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
252 CI != E; ++CI)
Chris Lattner50754772007-10-17 21:28:00 +0000253 if (*CI)
Chris Lattnere64b7772007-10-24 16:57:36 +0000254 *CI = RewriteFunctionBody(*CI);
Steve Naroffebf2b562007-10-23 23:50:29 +0000255
256 // Handle specific things.
257 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
258 return RewriteAtEncode(AtEncode);
259
Steve Naroff934f2762007-10-24 22:48:43 +0000260 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
261 // Before we rewrite it, put the original message expression in a comment.
262 SourceLocation startLoc = MessExpr->getLocStart();
263 SourceLocation endLoc = MessExpr->getLocEnd();
264
265 const char *startBuf = SM->getCharacterData(startLoc);
266 const char *endBuf = SM->getCharacterData(endLoc);
267
268 std::string messString;
269 messString += "// ";
270 messString.append(startBuf, endBuf-startBuf+1);
271 messString += "\n";
272
273 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
274 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
275 // Tried this, but it didn't work either...
276 // Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffebf2b562007-10-23 23:50:29 +0000277 return RewriteMessageExpr(MessExpr);
Steve Naroff934f2762007-10-24 22:48:43 +0000278 }
Chris Lattnere64b7772007-10-24 16:57:36 +0000279 // Return this stmt unmodified.
280 return S;
Chris Lattner311ff022007-10-16 22:36:42 +0000281}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000282
Chris Lattnere64b7772007-10-24 16:57:36 +0000283Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattner01c57482007-10-17 22:35:30 +0000284 // Create a new string expression.
285 QualType StrType = Context->getPointerType(Context->CharTy);
286 Expr *Replacement = new StringLiteral("foo", 3, false, StrType,
287 SourceLocation(), SourceLocation());
288 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattnere64b7772007-10-24 16:57:36 +0000289 delete Exp;
290 return Replacement;
Chris Lattner311ff022007-10-16 22:36:42 +0000291}
292
Steve Naroff934f2762007-10-24 22:48:43 +0000293CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
294 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffebf2b562007-10-23 23:50:29 +0000295 // Get the type, we will need to reference it in a couple spots.
Steve Naroff934f2762007-10-24 22:48:43 +0000296 QualType msgSendType = FD->getType();
Steve Naroffebf2b562007-10-23 23:50:29 +0000297
298 // Create a reference to the objc_msgSend() declaration.
Steve Naroff934f2762007-10-24 22:48:43 +0000299 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffebf2b562007-10-23 23:50:29 +0000300
301 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerf04da132007-10-24 17:06:59 +0000302 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffebf2b562007-10-23 23:50:29 +0000303 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
304
305 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattnere64b7772007-10-24 16:57:36 +0000306
Steve Naroff934f2762007-10-24 22:48:43 +0000307 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
308}
309
310Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
311 assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
312 assert(SelGetUidFunctionDecl && "Can't find sel_getUid() decl");
313 assert(GetClassFunctionDecl && "Can't find objc_getClass() decl");
314
315 // Synthesize a call to objc_msgSend().
316 llvm::SmallVector<Expr*, 8> MsgExprs;
317 IdentifierInfo *clsName = Exp->getClassName();
318
319 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
320 if (clsName) { // class message.
321 llvm::SmallVector<Expr*, 8> ClsExprs;
322 QualType argType = Context->getPointerType(Context->CharTy);
323 ClsExprs.push_back(new StringLiteral(clsName->getName(),
324 clsName->getLength(),
325 false, argType, SourceLocation(),
326 SourceLocation()));
327 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
328 &ClsExprs[0], ClsExprs.size());
329 MsgExprs.push_back(Cls);
330 } else // instance message.
331 MsgExprs.push_back(Exp->getReceiver());
332
333 // Create a call to sel_getUid("selName"), it will be the 2nd argument.
334 llvm::SmallVector<Expr*, 8> SelExprs;
335 QualType argType = Context->getPointerType(Context->CharTy);
336 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
337 Exp->getSelector().getName().size(),
338 false, argType, SourceLocation(),
339 SourceLocation()));
340 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
341 &SelExprs[0], SelExprs.size());
342 MsgExprs.push_back(SelExp);
343
344 // Now push any user supplied arguments.
345 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
346 MsgExprs.push_back(Exp->getArg(i));
347 // We've transferred the ownership to MsgExprs. Null out the argument in
348 // the original expression, since we will delete it below.
349 Exp->setArg(i, 0);
350 }
351 CallExpr *MessExp = SynthesizeCallToFunctionDecl(MsgSendFunctionDecl,
352 &MsgExprs[0], MsgExprs.size());
353 // Now do the actual rewrite.
354 Rewrite.ReplaceStmt(Exp, MessExp);
355
Chris Lattnere64b7772007-10-24 16:57:36 +0000356 delete Exp;
Steve Naroff934f2762007-10-24 22:48:43 +0000357 return MessExp;
Steve Naroffebf2b562007-10-23 23:50:29 +0000358}
359
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000360// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
361/// class methods.
362void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
363 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000364 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000365 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +0000366 const char *ClassName,
367 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000368 static bool objc_impl_method = false;
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000369 if (NumMethods > 0 && !objc_impl_method) {
370 /* struct _objc_method {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000371 SEL _cmd;
372 char *method_types;
373 void *_imp;
374 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000375 */
Chris Lattner158ecb92007-10-25 17:07:24 +0000376 Result += "\nstruct _objc_method {\n";
377 Result += "\tSEL _cmd;\n";
378 Result += "\tchar *method_types;\n";
379 Result += "\tvoid *_imp;\n";
380 Result += "};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000381 objc_impl_method = true;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000382 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000383 // Build _objc_method_list for class's methods if needed
384 if (NumMethods > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000385 /* struct _objc_method_list {
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000386 struct _objc_method_list *next_method;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000387 int method_count;
388 struct _objc_method method_list[method_count];
389 }
390 */
Chris Lattner158ecb92007-10-25 17:07:24 +0000391 Result += "\nstatic struct {\n";
392 Result += "\tstruct _objc_method_list *next_method;\n";
393 Result += "\tint method_count;\n";
394 Result += "\tstruct _objc_method method_list[" + utostr(NumMethods) +"];\n";
395 Result += "} _OBJC_";
396 Result += prefix;
397 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
398 Result += "_METHODS_";
399 Result += ClassName;
400 Result += " __attribute__ ((section (\"__OBJC, __";
401 Result += IsInstanceMethod ? "inst" : "cls";
402 Result += "_meth\")))= {\n\t0, " + utostr(NumMethods) + "\n";
403
404 for (int i = 0; i < NumMethods; i++) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000405 // TODO: 1) method selector name may hav to go into their own section
406 // 2) encode method types for use here (which may have to go into
407 // __meth_var_types section, 3) Need method address as 3rd initializer.
Chris Lattner158ecb92007-10-25 17:07:24 +0000408 Result += "\t,(SEL)\"" + Methods[i]->getSelector().getName() +
409 "\", \"\", 0\n";
410 }
411 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000412 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000413}
414
415/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
416void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
417 int NumProtocols,
418 const char *prefix,
419 const char *ClassName) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000420 static bool objc_protocol_methods = false;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000421 if (NumProtocols > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000422 for (int i = 0; i < NumProtocols; i++) {
423 ObjcProtocolDecl *PDecl = Protocols[i];
424 // Output struct protocol_methods holder of method selector and type.
425 if (!objc_protocol_methods &&
426 (PDecl->getNumInstanceMethods() > 0
427 || PDecl->getNumClassMethods() > 0)) {
428 /* struct protocol_methods {
429 SEL _cmd;
430 char *method_types;
431 }
432 */
433 printf("\nstruct protocol_methods {\n");
434 printf("\tSEL _cmd;\n");
435 printf("\tchar *method_types;\n");
436 printf("};\n");
437 objc_protocol_methods = true;
438 }
439 // Output instance methods declared in this protocol.
440 /* struct _objc_protocol_method_list {
441 int protocol_method_count;
442 struct protocol_methods protocols[protocol_method_count];
443 }
444 */
445 int NumMethods = PDecl->getNumInstanceMethods();
446 if (NumMethods > 0) {
447 printf("\nstatic struct {\n");
448 printf("\tint protocol_method_count;\n");
449 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
450 printf("} _OBJC_PROTOCOL_INSTANCE_METHODS_%s "
451 "__attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
452 "{\n\t%d\n",PDecl->getName(), NumMethods);
453 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
454 for (int i = 0; i < NumMethods; i++)
455 // TODO: 1) method selector name may hav to go into their own section
456 // 2) encode method types for use here (which may have to go into
457 // __meth_var_types section.
458 printf("\t,(SEL)\"%s\", \"\"\n",
459 Methods[i]->getSelector().getName().c_str());
460 printf("};\n");
461 }
462
463 // Output class methods declared in this protocol.
464 NumMethods = PDecl->getNumClassMethods();
465 if (NumMethods > 0) {
466 printf("\nstatic struct {\n");
467 printf("\tint protocol_method_count;\n");
468 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
469 printf("} _OBJC_PROTOCOL_CLASS_METHODS_%s "
470 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
471 "{\n\t%d\n",PDecl->getName(), NumMethods);
472 ObjcMethodDecl **Methods = PDecl->getClassMethods();
473 for (int i = 0; i < NumMethods; i++)
474 // TODO: 1) method selector name may hav to go into their own section
475 // 2) encode method types for use here (which may have to go into
476 // __meth_var_types section.
477 printf("\t,(SEL)\"%s\", \"\"\n",
478 Methods[i]->getSelector().getName().c_str());
479 printf("};\n");
480 }
481 // Output:
482 /* struct _objc_protocol {
483 // Objective-C 1.0 extensions
484 struct _objc_protocol_extension *isa;
485 char *protocol_name;
486 struct _objc_protocol **protocol_list;
487 struct _objc__method_prototype_list *instance_methods;
488 struct _objc__method_prototype_list *class_methods;
489 };
490 */
491 static bool objc_protocol = false;
492 if (!objc_protocol) {
493 printf("\nstruct _objc_protocol {\n");
494 printf("\tstruct _objc_protocol_extension *isa;\n");
495 printf("\tchar *protocol_name;\n");
496 printf("\tstruct _objc_protocol **protocol_list;\n");
497 printf("\tstruct _objc__method_prototype_list *instance_methods;\n");
498 printf("\tstruct _objc__method_prototype_list *class_methods;\n");
499 printf("};\n");
500 objc_protocol = true;
501 }
502
503 printf("\nstatic struct _objc_protocol _OBJC_PROTOCOL_%s "
504 "__attribute__ ((section (\"__OBJC, __protocol\")))= "
505 "{\n\t0, \"%s\", 0, ", PDecl->getName(), PDecl->getName());
506 if (PDecl->getInstanceMethods() > 0)
507 printf("(struct _objc__method_prototype_list *)"
508 "&_OBJC_PROTOCOL_INSTANCE_METHODS_%s, ", PDecl->getName());
509 else
510 printf("0, ");
511 if (PDecl->getClassMethods() > 0)
512 printf("(struct _objc__method_prototype_list *)"
513 "&_OBJC_PROTOCOL_CLASS_METHODS_%s\n", PDecl->getName());
514 else
515 printf("0\n");
516 printf("};\n");
517 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000518 // Output the top lovel protocol meta-data for the class.
519 /* struct _objc_protocol_list {
520 struct _objc_protocol_list *next;
521 int protocol_count;
522 struct _objc_protocol *class_protocols[protocol_count];
523 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000524 */
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000525 printf("\nstatic struct {\n");
526 printf("\tstruct _objc_protocol_list *next;\n");
527 printf("\tint protocol_count;\n");
528 printf("\tstruct _objc_protocol *class_protocols[%d];\n"
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000529 "} _OBJC_%s_PROTOCOLS_%s "
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000530 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000531 "{\n\t0, %d\n",NumProtocols, prefix,
532 ClassName, NumProtocols);
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000533 for (int i = 0; i < NumProtocols; i++) {
534 ObjcProtocolDecl *PDecl = Protocols[i];
535 printf("\t,&_OBJC_PROTOCOL_%s \n",
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000536 PDecl->getName());
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000537 }
538 printf("};\n");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000539 }
540}
541
542/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
543/// implementation.
544void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl) {
545 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
546 // Find category declaration for this implementation.
547 ObjcCategoryDecl *CDecl;
548 for (CDecl = ClassDecl->getCategoryList(); CDecl;
549 CDecl = CDecl->getNextClassCategory())
550 if (CDecl->getIdentifier() == IDecl->getIdentifier())
551 break;
552 assert(CDecl && "RewriteObjcCategoryImplDecl - bad category");
553
554 char *FullCategoryName = (char*)alloca(
555 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
556 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
557
Chris Lattner158ecb92007-10-25 17:07:24 +0000558 std::string ResultStr;
559
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000560 // Build _objc_method_list for class's instance methods if needed
561 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
562 IDecl->getNumInstanceMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000563 true,
Chris Lattner158ecb92007-10-25 17:07:24 +0000564 "CATEGORY_", FullCategoryName, ResultStr);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000565
566 // Build _objc_method_list for class's class methods if needed
567 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
568 IDecl->getNumClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000569 false,
Chris Lattner158ecb92007-10-25 17:07:24 +0000570 "CATEGORY_", FullCategoryName, ResultStr);
571
572 // For now just print the string out. It should be passed to the other
573 // functions to collect all metadata info into the string.
574 printf("%s", ResultStr.c_str());
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000575
576 // Protocols referenced in class declaration?
577 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
578 CDecl->getNumReferencedProtocols(),
579 "CATEGORY",
580 FullCategoryName);
581
582 /* struct _objc_category {
583 char *category_name;
584 char *class_name;
585 struct _objc_method_list *instance_methods;
586 struct _objc_method_list *class_methods;
587 struct _objc_protocol_list *protocols;
588 // Objective-C 1.0 extensions
589 uint32_t size; // sizeof (struct _objc_category)
590 struct _objc_property_list *instance_properties; // category's own
591 // @property decl.
592 };
593 */
594
595 static bool objc_category = false;
596 if (!objc_category) {
597 printf("\nstruct _objc_category {\n");
598 printf("\tchar *category_name;\n");
599 printf("\tchar *class_name;\n");
600 printf("\tstruct _objc_method_list *instance_methods;\n");
601 printf("\tstruct _objc_method_list *class_methods;\n");
602 printf("\tstruct _objc_protocol_list *protocols;\n");
603 printf("\tunsigned int size;\n");
604 printf("\tstruct _objc_property_list *instance_properties;\n");
605 printf("};\n");
606 objc_category = true;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000607 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000608 printf("\nstatic struct _objc_category _OBJC_CATEGORY_%s "
609 "__attribute__ ((section (\"__OBJC, __category\")))= {\n"
610 "\t\"%s\"\n\t, \"%s\"\n",FullCategoryName,
611 IDecl->getName(),
612 ClassDecl->getName());
613 if (IDecl->getNumInstanceMethods() > 0)
614 printf("\t, (struct _objc_method_list *)"
615 "&_OBJC_CATEGORY_INSTANCE_METHODS_%s\n",
616 FullCategoryName);
617 else
618 printf("\t, 0\n");
619 if (IDecl->getNumClassMethods() > 0)
620 printf("\t, (struct _objc_method_list *)"
621 "&_OBJC_CATEGORY_CLASS_METHODS_%s\n",
622 FullCategoryName);
623 else
624 printf("\t, 0\n");
625
626 if (CDecl->getNumReferencedProtocols() > 0)
627 printf("\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_%s\n",
628 FullCategoryName);
629 else
630 printf("\t, 0\n");
Fariborz Jahanian1a0965e2007-10-24 21:25:12 +0000631 printf("\t, sizeof(struct _objc_category), 0\n};\n");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000632}
633
634//===----------------------------------------------------------------------===//
635// Meta Data Emission
636//===----------------------------------------------------------------------===//
637
638void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl) {
639 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
640
641 // Build _objc_ivar_list metadata for classes ivars if needed
642 int NumIvars = IDecl->getImplDeclNumIvars() > 0
643 ? IDecl->getImplDeclNumIvars()
644 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
645
646 if (NumIvars > 0) {
647 static bool objc_ivar = false;
648 if (!objc_ivar) {
649 /* struct _objc_ivar {
650 char *ivar_name;
651 char *ivar_type;
652 int ivar_offset;
653 };
654 */
655 printf("\nstruct _objc_ivar {\n");
656 printf("\tchar *ivar_name;\n");
657 printf("\tchar *ivar_type;\n");
658 printf("\tint ivar_offset;\n");
659 printf("};\n");
660 objc_ivar = true;
661 }
662
663 /* struct _objc_ivar_list {
664 int ivar_count;
665 struct _objc_ivar ivar_list[ivar_count];
666 };
667 */
668 printf("\nstatic struct {\n");
669 printf("\tint ivar_count;\n");
670 printf("\tstruct _objc_ivar ivar_list[%d];\n", NumIvars);
671 printf("} _OBJC_INSTANCE_VARIABLES_%s "
672 "__attribute__ ((section (\"__OBJC, __instance_vars\")))= "
673 "{\n\t%d\n",IDecl->getName(),
674 NumIvars);
675 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
676 ? IDecl->getImplDeclIVars()
677 : CDecl->getIntfDeclIvars();
678 for (int i = 0; i < NumIvars; i++)
679 // TODO: 1) ivar names may have to go to another section. 2) encode
680 // ivar_type type of each ivar . 3) compute and add ivar offset.
681 printf("\t,\"%s\", \"\", 0\n", Ivars[i]->getName());
682 printf("};\n");
683 }
684
Chris Lattner158ecb92007-10-25 17:07:24 +0000685 std::string ResultStr;
686
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000687 // Build _objc_method_list for class's instance methods if needed
688 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
689 IDecl->getNumInstanceMethods(),
Chris Lattner158ecb92007-10-25 17:07:24 +0000690 true, "", IDecl->getName(), ResultStr);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000691
692 // Build _objc_method_list for class's class methods if needed
693 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000694 IDecl->getNumClassMethods(),
Chris Lattner158ecb92007-10-25 17:07:24 +0000695 false, "", IDecl->getName(), ResultStr);
696
697 // For now just print the string out. It should be passed to the other
698 // functions to collect all metadata info into the string.
699 printf("%s", ResultStr.c_str());
700
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000701 // Protocols referenced in class declaration?
702 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
703 CDecl->getNumIntfRefProtocols(),
704 "CLASS",
705 CDecl->getName());
706
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000707
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000708 // Declaration of class/meta-class metadata
709 /* struct _objc_class {
710 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000711 const char *super_class_name;
712 char *name;
713 long version;
714 long info;
715 long instance_size;
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000716 struct _objc_ivar_list *ivars;
717 struct _objc_method_list *methods;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000718 struct objc_cache *cache;
719 struct objc_protocol_list *protocols;
720 const char *ivar_layout;
721 struct _objc_class_ext *ext;
722 };
723 */
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000724 static bool objc_class = false;
725 if (!objc_class) {
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000726 printf("\nstruct _objc_class {\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000727 printf("\tstruct _objc_class *isa;\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000728 printf("\tconst char *super_class_name;\n");
729 printf("\tchar *name;\n");
730 printf("\tlong version;\n");
731 printf("\tlong info;\n");
732 printf("\tlong instance_size;\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000733 printf("\tstruct _objc_ivar_list *ivars;\n");
734 printf("\tstruct _objc_method_list *methods;\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000735 printf("\tstruct objc_cache *cache;\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000736 printf("\tstruct _objc_protocol_list *protocols;\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000737 printf("\tconst char *ivar_layout;\n");
738 printf("\tstruct _objc_class_ext *ext;\n");
739 printf("};\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000740 objc_class = true;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000741 }
742
743 // Meta-class metadata generation.
744 ObjcInterfaceDecl *RootClass = 0;
745 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
746 while (SuperClass) {
747 RootClass = SuperClass;
748 SuperClass = SuperClass->getSuperClass();
749 }
750 SuperClass = CDecl->getSuperClass();
751
752 printf("\nstatic struct _objc_class _OBJC_METACLASS_%s "
753 "__attribute__ ((section (\"__OBJC, __meta_class\")))= "
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000754 "{\n\t(struct _objc_class *)\"%s\"",
755 CDecl->getName(), RootClass ? RootClass->getName()
756 : CDecl->getName());
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000757 if (SuperClass)
758 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
759 else
760 printf(", 0, \"%s\"", CDecl->getName());
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000761 // TODO: 'ivars' field for root class is currently set to 0.
762 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahanian1a0965e2007-10-24 21:25:12 +0000763 printf(", 0,2, sizeof(struct _objc_class), 0");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000764 if (CDecl->getNumClassMethods() > 0)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000765 printf("\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_%s\n",
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000766 CDecl->getName());
767 else
768 printf(", 0\n");
Fariborz Jahanian454cb012007-10-24 20:54:23 +0000769 if (CDecl->getNumIntfRefProtocols() > 0)
770 printf("\t,0,(struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_%s,0,0\n",
771 CDecl->getName());
772 else
773 printf("\t,0,0,0,0\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000774 printf("};\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000775
776 // class metadata generation.
777 printf("\nstatic struct _objc_class _OBJC_CLASS_%s "
778 "__attribute__ ((section (\"__OBJC, __class\")))= "
779 "{\n\t&_OBJC_METACLASS_%s", CDecl->getName(), CDecl->getName());
780 if (SuperClass)
781 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
782 else
783 printf(", 0, \"%s\"", CDecl->getName());
784 // 'info' field is initialized to CLS_CLASS(1) for class
785 // TODO: instance_size is curently set to 0.
786 printf(", 0,1,0");
787 if (NumIvars > 0)
788 printf(", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_%s\n\t",
789 CDecl->getName());
790 else
791 printf(",0");
792 if (IDecl->getNumInstanceMethods() > 0)
793 printf(", (struct _objc_method_list*)&_OBJC_INSTANCE_METHODS_%s, 0\n\t",
794 CDecl->getName());
795 else
796 printf(",0,0");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000797 if (CDecl->getNumIntfRefProtocols() > 0)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000798 printf(", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_%s, 0,0\n",
799 CDecl->getName());
800 else
801 printf(",0,0,0\n");
802 printf("};\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000803}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000804
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000805void RewriteTest::WriteObjcMetaData() {
806 int ClsDefCount = ClassImplementation.size();
807 int CatDefCount = CategoryImplementation.size();
808 if (ClsDefCount == 0 && CatDefCount == 0)
809 return;
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000810
Fariborz Jahanian454cb012007-10-24 20:54:23 +0000811 // TODO: This is temporary until we decide how to access objc types in a
812 // c program
813 printf("\n#include <Objc/objc.h>\n");
814
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000815 // For each implemented class, write out all its meta data.
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000816 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000817 RewriteObjcClassMetaData(ClassImplementation[i]);
818
819 // For each implemented category, write out all its meta data.
820 for (int i = 0; i < CatDefCount; i++)
821 RewriteObjcCategoryImplDecl(CategoryImplementation[i]);
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000822
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000823 // Write objc_symtab metadata
824 /*
825 struct _objc_symtab
826 {
827 long sel_ref_cnt;
828 SEL *refs;
829 short cls_def_cnt;
830 short cat_def_cnt;
831 void *defs[cls_def_cnt + cat_def_cnt];
832 };
833 */
834
835 printf("\nstruct _objc_symtab {\n");
836 printf("\tlong sel_ref_cnt;\n");
837 printf("\tSEL *refs;\n");
838 printf("\tshort cls_def_cnt;\n");
839 printf("\tshort cat_def_cnt;\n");
840 printf("\tvoid *defs[%d];\n", ClsDefCount + CatDefCount);
841 printf("};\n\n");
842
843 printf("static struct _objc_symtab "
Chris Lattnerf04da132007-10-24 17:06:59 +0000844 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n");
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000845 printf("\t0, 0, %d, %d\n", ClsDefCount, CatDefCount);
846 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000847 printf("\t,&_OBJC_CLASS_%s\n", ClassImplementation[i]->getName());
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000848
849 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000850 printf("\t,&_OBJC_CATEGORY_%s_%s\n",
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000851 CategoryImplementation[i]->getClassInterface()->getName(),
852 CategoryImplementation[i]->getName());
853
854 printf("};\n\n");
855
856 // Write objc_module metadata
857
858 /*
859 struct _objc_module {
860 long version;
861 long size;
862 const char *name;
863 struct _objc_symtab *symtab;
864 }
865 */
866
867 printf("\nstruct _objc_module {\n");
868 printf("\tlong version;\n");
869 printf("\tlong size;\n");
870 printf("\tconst char *name;\n");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000871 printf("\tstruct _objc_symtab *symtab;\n");
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000872 printf("};\n\n");
873 printf("static struct _objc_module "
874 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n");
Fariborz Jahanian1a0965e2007-10-24 21:25:12 +0000875 printf("\t%d, sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n", OBJC_ABI_VERSION);
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000876 printf("};\n\n");
877}
Chris Lattner311ff022007-10-16 22:36:42 +0000878