blob: 17fd0473fce6ec89d4c551734350595061e5b3a8 [file] [log] [blame]
Chris Lattner77cd2a02007-10-11 00:43:27 +00001//===--- RewriteTest.cpp - Playground for the code rewriter ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Hacks and fun related to the code rewriter.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ASTConsumers.h"
Chris Lattner8a12c272007-10-11 18:38:32 +000015#include "clang/Rewrite/Rewriter.h"
Chris Lattner77cd2a02007-10-11 00:43:27 +000016#include "clang/AST/AST.h"
17#include "clang/AST/ASTConsumer.h"
Chris Lattner8a12c272007-10-11 18:38:32 +000018#include "clang/Basic/SourceManager.h"
Steve Naroffebf2b562007-10-23 23:50:29 +000019#include "clang/Basic/IdentifierTable.h"
Chris Lattner77cd2a02007-10-11 00:43:27 +000020using namespace clang;
21
Chris Lattner77cd2a02007-10-11 00:43:27 +000022namespace {
Chris Lattner8a12c272007-10-11 18:38:32 +000023 class RewriteTest : public ASTConsumer {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000024 Rewriter Rewrite;
Chris Lattner01c57482007-10-17 22:35:30 +000025 ASTContext *Context;
Chris Lattner77cd2a02007-10-11 00:43:27 +000026 SourceManager *SM;
Chris Lattner8a12c272007-10-11 18:38:32 +000027 unsigned MainFileID;
Chris Lattner2c64b7b2007-10-16 21:07:07 +000028 SourceLocation LastIncLoc;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000029 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
30 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Steve Naroffebf2b562007-10-23 23:50:29 +000031
32 FunctionDecl *MsgSendFunctionDecl;
33 FunctionDecl *GetClassFunctionDecl;
Steve Naroff934f2762007-10-24 22:48:43 +000034 FunctionDecl *SelGetUidFunctionDecl;
Steve Naroffebf2b562007-10-23 23:50:29 +000035
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;
Steve Naroffc0006092007-10-24 01:09:48 +000043 GetClassFunctionDecl = 0;
Steve Naroff934f2762007-10-24 22:48:43 +000044 SelGetUidFunctionDecl = 0;
Chris Lattner01c57482007-10-17 22:35:30 +000045 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattner77cd2a02007-10-11 00:43:27 +000046 }
Chris Lattner8a12c272007-10-11 18:38:32 +000047
Chris Lattnerf04da132007-10-24 17:06:59 +000048 // Top Level Driver code.
49 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner2c64b7b2007-10-16 21:07:07 +000050 void HandleDeclInMainFile(Decl *D);
Chris Lattnerf04da132007-10-24 17:06:59 +000051 ~RewriteTest();
52
53 // Syntactic Rewriting.
Chris Lattner2c64b7b2007-10-16 21:07:07 +000054 void RewriteInclude(SourceLocation Loc);
Chris Lattnerf04da132007-10-24 17:06:59 +000055 void RewriteTabs();
56 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Chris Lattner311ff022007-10-16 22:36:42 +000057
Chris Lattnerf04da132007-10-24 17:06:59 +000058 // Expression Rewriting.
Chris Lattnere64b7772007-10-24 16:57:36 +000059 Stmt *RewriteFunctionBody(Stmt *S);
60 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
61 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroff934f2762007-10-24 22:48:43 +000062 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
63 Expr **args, unsigned nargs);
Chris Lattnerf04da132007-10-24 17:06:59 +000064 // Metadata emission.
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000065 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl);
66
67 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl);
68
69 void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
70 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +000071 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000072 const char *prefix,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000073 const char *ClassName);
74
75 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
76 int NumProtocols,
77 const char *prefix,
78 const char *ClassName);
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000079 void WriteObjcMetaData();
Chris Lattner77cd2a02007-10-11 00:43:27 +000080 };
81}
82
Chris Lattner8a12c272007-10-11 18:38:32 +000083ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattner77cd2a02007-10-11 00:43:27 +000084
Chris Lattnerf04da132007-10-24 17:06:59 +000085//===----------------------------------------------------------------------===//
86// Top Level Driver Code
87//===----------------------------------------------------------------------===//
88
Chris Lattner8a12c272007-10-11 18:38:32 +000089void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000090 // Two cases: either the decl could be in the main file, or it could be in a
91 // #included file. If the former, rewrite it now. If the later, check to see
92 // if we rewrote the #include/#import.
93 SourceLocation Loc = D->getLocation();
94 Loc = SM->getLogicalLoc(Loc);
95
96 // If this is for a builtin, ignore it.
97 if (Loc.isInvalid()) return;
98
Steve Naroffebf2b562007-10-23 23:50:29 +000099 // Look for built-in declarations that we need to refer during the rewrite.
100 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroffc0006092007-10-24 01:09:48 +0000101 if (strcmp(FD->getName(), "objc_msgSend") == 0)
Steve Naroffebf2b562007-10-23 23:50:29 +0000102 MsgSendFunctionDecl = FD;
Steve Naroffc0006092007-10-24 01:09:48 +0000103 else if (strcmp(FD->getName(), "objc_getClass") == 0)
Steve Naroffebf2b562007-10-23 23:50:29 +0000104 GetClassFunctionDecl = FD;
Steve Naroff934f2762007-10-24 22:48:43 +0000105 else if (strcmp(FD->getName(), "sel_getUid") == 0)
106 SelGetUidFunctionDecl = FD;
Steve Naroffebf2b562007-10-23 23:50:29 +0000107 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000108
109 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000110 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
111 return HandleDeclInMainFile(D);
112
Chris Lattnerf04da132007-10-24 17:06:59 +0000113 // Otherwise, see if there is a #import in the main file that should be
114 // rewritten.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000115 RewriteInclude(Loc);
116}
117
Chris Lattnerf04da132007-10-24 17:06:59 +0000118/// HandleDeclInMainFile - This is called for each top-level decl defined in the
119/// main file of the input.
120void RewriteTest::HandleDeclInMainFile(Decl *D) {
121 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
122 if (Stmt *Body = FD->getBody())
123 FD->setBody(RewriteFunctionBody(Body));
124
125 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
126 ClassImplementation.push_back(CI);
127 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
128 CategoryImplementation.push_back(CI);
129 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
130 RewriteForwardClassDecl(CD);
131 // Nothing yet.
132}
133
134RewriteTest::~RewriteTest() {
135 // Get the top-level buffer that this corresponds to.
136 RewriteTabs();
137
138 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
139 // we are done.
140 if (const RewriteBuffer *RewriteBuf =
141 Rewrite.getRewriteBufferFor(MainFileID)) {
142 printf("Changed:\n");
143 std::string S(RewriteBuf->begin(), RewriteBuf->end());
144 printf("%s\n", S.c_str());
145 } else {
146 printf("No changes\n");
147 }
148
149 // Rewrite Objective-c meta data*
150 WriteObjcMetaData();
151}
152
153//===----------------------------------------------------------------------===//
154// Syntactic (non-AST) Rewriting Code
155//===----------------------------------------------------------------------===//
156
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000157void RewriteTest::RewriteInclude(SourceLocation Loc) {
158 // Rip up the #include stack to the main file.
159 SourceLocation IncLoc = Loc, NextLoc = Loc;
160 do {
161 IncLoc = Loc;
162 Loc = SM->getLogicalLoc(NextLoc);
163 NextLoc = SM->getIncludeLoc(Loc);
164 } while (!NextLoc.isInvalid());
165
166 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
167 // IncLoc indicates the header that was included if it is useful.
168 IncLoc = SM->getLogicalLoc(IncLoc);
169 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
170 Loc == LastIncLoc)
171 return;
172 LastIncLoc = Loc;
173
174 unsigned IncCol = SM->getColumnNumber(Loc);
175 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
176
177 // Replace the #import with #include.
178 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
179}
180
Chris Lattnerf04da132007-10-24 17:06:59 +0000181void RewriteTest::RewriteTabs() {
182 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
183 const char *MainBufStart = MainBuf.first;
184 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000185
Chris Lattnerf04da132007-10-24 17:06:59 +0000186 // Loop over the whole file, looking for tabs.
187 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
188 if (*BufPtr != '\t')
189 continue;
190
191 // Okay, we found a tab. This tab will turn into at least one character,
192 // but it depends on which 'virtual column' it is in. Compute that now.
193 unsigned VCol = 0;
194 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
195 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
196 ++VCol;
197
198 // Okay, now that we know the virtual column, we know how many spaces to
199 // insert. We assume 8-character tab-stops.
200 unsigned Spaces = 8-(VCol & 7);
201
202 // Get the location of the tab.
203 SourceLocation TabLoc =
204 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
205
206 // Rewrite the single tab character into a sequence of spaces.
207 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
208 }
Chris Lattner8a12c272007-10-11 18:38:32 +0000209}
210
211
Chris Lattnerf04da132007-10-24 17:06:59 +0000212void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
213 int numDecls = ClassDecl->getNumForwardDecls();
214 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
215
216 // Get the start location and compute the semi location.
217 SourceLocation startLoc = ClassDecl->getLocation();
218 const char *startBuf = SM->getCharacterData(startLoc);
219 const char *semiPtr = strchr(startBuf, ';');
220
221 // Translate to typedef's that forward reference structs with the same name
222 // as the class. As a convenience, we include the original declaration
223 // as a comment.
224 std::string typedefString;
225 typedefString += "// ";
Steve Naroff934f2762007-10-24 22:48:43 +0000226 typedefString.append(startBuf, semiPtr-startBuf+1);
227 typedefString += "\n";
228 for (int i = 0; i < numDecls; i++) {
229 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
230 typedefString += "typedef struct ";
231 typedefString += ForwardDecl->getName();
232 typedefString += " ";
233 typedefString += ForwardDecl->getName();
234 typedefString += ";\n";
235 }
236
237 // Replace the @class with typedefs corresponding to the classes.
238 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
239 typedefString.c_str(), typedefString.size());
Chris Lattnerf04da132007-10-24 17:06:59 +0000240}
241
242//===----------------------------------------------------------------------===//
243// Function Body / Expression rewriting
244//===----------------------------------------------------------------------===//
245
Chris Lattnere64b7772007-10-24 16:57:36 +0000246Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner311ff022007-10-16 22:36:42 +0000247 // Otherwise, just rewrite all children.
248 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
249 CI != E; ++CI)
Chris Lattner50754772007-10-17 21:28:00 +0000250 if (*CI)
Chris Lattnere64b7772007-10-24 16:57:36 +0000251 *CI = RewriteFunctionBody(*CI);
Steve Naroffebf2b562007-10-23 23:50:29 +0000252
253 // Handle specific things.
254 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
255 return RewriteAtEncode(AtEncode);
256
Steve Naroff934f2762007-10-24 22:48:43 +0000257 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
258 // Before we rewrite it, put the original message expression in a comment.
259 SourceLocation startLoc = MessExpr->getLocStart();
260 SourceLocation endLoc = MessExpr->getLocEnd();
261
262 const char *startBuf = SM->getCharacterData(startLoc);
263 const char *endBuf = SM->getCharacterData(endLoc);
264
265 std::string messString;
266 messString += "// ";
267 messString.append(startBuf, endBuf-startBuf+1);
268 messString += "\n";
269
270 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
271 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
272 // Tried this, but it didn't work either...
273 // Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffebf2b562007-10-23 23:50:29 +0000274 return RewriteMessageExpr(MessExpr);
Steve Naroff934f2762007-10-24 22:48:43 +0000275 }
Chris Lattnere64b7772007-10-24 16:57:36 +0000276 // Return this stmt unmodified.
277 return S;
Chris Lattner311ff022007-10-16 22:36:42 +0000278}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000279
Chris Lattnere64b7772007-10-24 16:57:36 +0000280Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattner01c57482007-10-17 22:35:30 +0000281 // Create a new string expression.
282 QualType StrType = Context->getPointerType(Context->CharTy);
283 Expr *Replacement = new StringLiteral("foo", 3, false, StrType,
284 SourceLocation(), SourceLocation());
285 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattnere64b7772007-10-24 16:57:36 +0000286 delete Exp;
287 return Replacement;
Chris Lattner311ff022007-10-16 22:36:42 +0000288}
289
Steve Naroff934f2762007-10-24 22:48:43 +0000290CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
291 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffebf2b562007-10-23 23:50:29 +0000292 // Get the type, we will need to reference it in a couple spots.
Steve Naroff934f2762007-10-24 22:48:43 +0000293 QualType msgSendType = FD->getType();
Steve Naroffebf2b562007-10-23 23:50:29 +0000294
295 // Create a reference to the objc_msgSend() declaration.
Steve Naroff934f2762007-10-24 22:48:43 +0000296 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffebf2b562007-10-23 23:50:29 +0000297
298 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerf04da132007-10-24 17:06:59 +0000299 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffebf2b562007-10-23 23:50:29 +0000300 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
301
302 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattnere64b7772007-10-24 16:57:36 +0000303
Steve Naroff934f2762007-10-24 22:48:43 +0000304 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
305}
306
307Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
308 assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
309 assert(SelGetUidFunctionDecl && "Can't find sel_getUid() decl");
310 assert(GetClassFunctionDecl && "Can't find objc_getClass() decl");
311
312 // Synthesize a call to objc_msgSend().
313 llvm::SmallVector<Expr*, 8> MsgExprs;
314 IdentifierInfo *clsName = Exp->getClassName();
315
316 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
317 if (clsName) { // class message.
318 llvm::SmallVector<Expr*, 8> ClsExprs;
319 QualType argType = Context->getPointerType(Context->CharTy);
320 ClsExprs.push_back(new StringLiteral(clsName->getName(),
321 clsName->getLength(),
322 false, argType, SourceLocation(),
323 SourceLocation()));
324 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
325 &ClsExprs[0], ClsExprs.size());
326 MsgExprs.push_back(Cls);
327 } else // instance message.
328 MsgExprs.push_back(Exp->getReceiver());
329
330 // Create a call to sel_getUid("selName"), it will be the 2nd argument.
331 llvm::SmallVector<Expr*, 8> SelExprs;
332 QualType argType = Context->getPointerType(Context->CharTy);
333 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
334 Exp->getSelector().getName().size(),
335 false, argType, SourceLocation(),
336 SourceLocation()));
337 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
338 &SelExprs[0], SelExprs.size());
339 MsgExprs.push_back(SelExp);
340
341 // Now push any user supplied arguments.
342 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
343 MsgExprs.push_back(Exp->getArg(i));
344 // We've transferred the ownership to MsgExprs. Null out the argument in
345 // the original expression, since we will delete it below.
346 Exp->setArg(i, 0);
347 }
348 CallExpr *MessExp = SynthesizeCallToFunctionDecl(MsgSendFunctionDecl,
349 &MsgExprs[0], MsgExprs.size());
350 // Now do the actual rewrite.
351 Rewrite.ReplaceStmt(Exp, MessExp);
352
Chris Lattnere64b7772007-10-24 16:57:36 +0000353 delete Exp;
Steve Naroff934f2762007-10-24 22:48:43 +0000354 return MessExp;
Steve Naroffebf2b562007-10-23 23:50:29 +0000355}
356
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000357// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
358/// class methods.
359void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
360 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000361 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000362 const char *prefix,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000363 const char *ClassName) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000364 static bool objc_impl_method = false;
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000365 if (NumMethods > 0 && !objc_impl_method) {
366 /* struct _objc_method {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000367 SEL _cmd;
368 char *method_types;
369 void *_imp;
370 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000371 */
372 printf("\nstruct _objc_method {\n");
373 printf("\tSEL _cmd;\n");
374 printf("\tchar *method_types;\n");
375 printf("\tvoid *_imp;\n");
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000376 printf("};\n");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000377 objc_impl_method = true;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000378 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000379 // Build _objc_method_list for class's methods if needed
380 if (NumMethods > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000381 /* struct _objc_method_list {
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000382 struct _objc_method_list *next_method;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000383 int method_count;
384 struct _objc_method method_list[method_count];
385 }
386 */
387 printf("\nstatic struct {\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000388 printf("\tstruct _objc_method_list *next_method;\n");
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000389 printf("\tint method_count;\n");
390 printf("\tstruct _objc_method method_list[%d];\n", NumMethods);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000391 printf("} _OBJC_%s%s_METHODS_%s "
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000392 "__attribute__ ((section (\"__OBJC, __%s_meth\")))= "
393 "{\n\t0, %d\n", prefix, IsInstanceMethod ? "INSTANCE" : "CLASS",
394 ClassName, IsInstanceMethod ? "inst" : "cls", NumMethods);
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000395 for (int i = 0; i < NumMethods; i++)
396 // TODO: 1) method selector name may hav to go into their own section
397 // 2) encode method types for use here (which may have to go into
398 // __meth_var_types section, 3) Need method address as 3rd initializer.
399 printf("\t,(SEL)\"%s\", \"\", 0\n",
400 Methods[i]->getSelector().getName().c_str());
401 printf("};\n");
402 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000403}
404
405/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
406void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
407 int NumProtocols,
408 const char *prefix,
409 const char *ClassName) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000410 static bool objc_protocol_methods = false;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000411 if (NumProtocols > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000412 for (int i = 0; i < NumProtocols; i++) {
413 ObjcProtocolDecl *PDecl = Protocols[i];
414 // Output struct protocol_methods holder of method selector and type.
415 if (!objc_protocol_methods &&
416 (PDecl->getNumInstanceMethods() > 0
417 || PDecl->getNumClassMethods() > 0)) {
418 /* struct protocol_methods {
419 SEL _cmd;
420 char *method_types;
421 }
422 */
423 printf("\nstruct protocol_methods {\n");
424 printf("\tSEL _cmd;\n");
425 printf("\tchar *method_types;\n");
426 printf("};\n");
427 objc_protocol_methods = true;
428 }
429 // Output instance methods declared in this protocol.
430 /* struct _objc_protocol_method_list {
431 int protocol_method_count;
432 struct protocol_methods protocols[protocol_method_count];
433 }
434 */
435 int NumMethods = PDecl->getNumInstanceMethods();
436 if (NumMethods > 0) {
437 printf("\nstatic struct {\n");
438 printf("\tint protocol_method_count;\n");
439 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
440 printf("} _OBJC_PROTOCOL_INSTANCE_METHODS_%s "
441 "__attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
442 "{\n\t%d\n",PDecl->getName(), NumMethods);
443 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
444 for (int i = 0; i < NumMethods; i++)
445 // TODO: 1) method selector name may hav to go into their own section
446 // 2) encode method types for use here (which may have to go into
447 // __meth_var_types section.
448 printf("\t,(SEL)\"%s\", \"\"\n",
449 Methods[i]->getSelector().getName().c_str());
450 printf("};\n");
451 }
452
453 // Output class methods declared in this protocol.
454 NumMethods = PDecl->getNumClassMethods();
455 if (NumMethods > 0) {
456 printf("\nstatic struct {\n");
457 printf("\tint protocol_method_count;\n");
458 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
459 printf("} _OBJC_PROTOCOL_CLASS_METHODS_%s "
460 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
461 "{\n\t%d\n",PDecl->getName(), NumMethods);
462 ObjcMethodDecl **Methods = PDecl->getClassMethods();
463 for (int i = 0; i < NumMethods; i++)
464 // TODO: 1) method selector name may hav to go into their own section
465 // 2) encode method types for use here (which may have to go into
466 // __meth_var_types section.
467 printf("\t,(SEL)\"%s\", \"\"\n",
468 Methods[i]->getSelector().getName().c_str());
469 printf("};\n");
470 }
471 // Output:
472 /* struct _objc_protocol {
473 // Objective-C 1.0 extensions
474 struct _objc_protocol_extension *isa;
475 char *protocol_name;
476 struct _objc_protocol **protocol_list;
477 struct _objc__method_prototype_list *instance_methods;
478 struct _objc__method_prototype_list *class_methods;
479 };
480 */
481 static bool objc_protocol = false;
482 if (!objc_protocol) {
483 printf("\nstruct _objc_protocol {\n");
484 printf("\tstruct _objc_protocol_extension *isa;\n");
485 printf("\tchar *protocol_name;\n");
486 printf("\tstruct _objc_protocol **protocol_list;\n");
487 printf("\tstruct _objc__method_prototype_list *instance_methods;\n");
488 printf("\tstruct _objc__method_prototype_list *class_methods;\n");
489 printf("};\n");
490 objc_protocol = true;
491 }
492
493 printf("\nstatic struct _objc_protocol _OBJC_PROTOCOL_%s "
494 "__attribute__ ((section (\"__OBJC, __protocol\")))= "
495 "{\n\t0, \"%s\", 0, ", PDecl->getName(), PDecl->getName());
496 if (PDecl->getInstanceMethods() > 0)
497 printf("(struct _objc__method_prototype_list *)"
498 "&_OBJC_PROTOCOL_INSTANCE_METHODS_%s, ", PDecl->getName());
499 else
500 printf("0, ");
501 if (PDecl->getClassMethods() > 0)
502 printf("(struct _objc__method_prototype_list *)"
503 "&_OBJC_PROTOCOL_CLASS_METHODS_%s\n", PDecl->getName());
504 else
505 printf("0\n");
506 printf("};\n");
507 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000508 // Output the top lovel protocol meta-data for the class.
509 /* struct _objc_protocol_list {
510 struct _objc_protocol_list *next;
511 int protocol_count;
512 struct _objc_protocol *class_protocols[protocol_count];
513 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000514 */
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000515 printf("\nstatic struct {\n");
516 printf("\tstruct _objc_protocol_list *next;\n");
517 printf("\tint protocol_count;\n");
518 printf("\tstruct _objc_protocol *class_protocols[%d];\n"
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000519 "} _OBJC_%s_PROTOCOLS_%s "
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000520 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000521 "{\n\t0, %d\n",NumProtocols, prefix,
522 ClassName, NumProtocols);
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000523 for (int i = 0; i < NumProtocols; i++) {
524 ObjcProtocolDecl *PDecl = Protocols[i];
525 printf("\t,&_OBJC_PROTOCOL_%s \n",
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000526 PDecl->getName());
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000527 }
528 printf("};\n");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000529 }
530}
531
532/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
533/// implementation.
534void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl) {
535 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
536 // Find category declaration for this implementation.
537 ObjcCategoryDecl *CDecl;
538 for (CDecl = ClassDecl->getCategoryList(); CDecl;
539 CDecl = CDecl->getNextClassCategory())
540 if (CDecl->getIdentifier() == IDecl->getIdentifier())
541 break;
542 assert(CDecl && "RewriteObjcCategoryImplDecl - bad category");
543
544 char *FullCategoryName = (char*)alloca(
545 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
546 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
547
548 // Build _objc_method_list for class's instance methods if needed
549 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
550 IDecl->getNumInstanceMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000551 true,
552 "CATEGORY_", FullCategoryName);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000553
554 // Build _objc_method_list for class's class methods if needed
555 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
556 IDecl->getNumClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000557 false,
558 "CATEGORY_", FullCategoryName);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000559
560 // Protocols referenced in class declaration?
561 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
562 CDecl->getNumReferencedProtocols(),
563 "CATEGORY",
564 FullCategoryName);
565
566 /* struct _objc_category {
567 char *category_name;
568 char *class_name;
569 struct _objc_method_list *instance_methods;
570 struct _objc_method_list *class_methods;
571 struct _objc_protocol_list *protocols;
572 // Objective-C 1.0 extensions
573 uint32_t size; // sizeof (struct _objc_category)
574 struct _objc_property_list *instance_properties; // category's own
575 // @property decl.
576 };
577 */
578
579 static bool objc_category = false;
580 if (!objc_category) {
581 printf("\nstruct _objc_category {\n");
582 printf("\tchar *category_name;\n");
583 printf("\tchar *class_name;\n");
584 printf("\tstruct _objc_method_list *instance_methods;\n");
585 printf("\tstruct _objc_method_list *class_methods;\n");
586 printf("\tstruct _objc_protocol_list *protocols;\n");
587 printf("\tunsigned int size;\n");
588 printf("\tstruct _objc_property_list *instance_properties;\n");
589 printf("};\n");
590 objc_category = true;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000591 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000592 printf("\nstatic struct _objc_category _OBJC_CATEGORY_%s "
593 "__attribute__ ((section (\"__OBJC, __category\")))= {\n"
594 "\t\"%s\"\n\t, \"%s\"\n",FullCategoryName,
595 IDecl->getName(),
596 ClassDecl->getName());
597 if (IDecl->getNumInstanceMethods() > 0)
598 printf("\t, (struct _objc_method_list *)"
599 "&_OBJC_CATEGORY_INSTANCE_METHODS_%s\n",
600 FullCategoryName);
601 else
602 printf("\t, 0\n");
603 if (IDecl->getNumClassMethods() > 0)
604 printf("\t, (struct _objc_method_list *)"
605 "&_OBJC_CATEGORY_CLASS_METHODS_%s\n",
606 FullCategoryName);
607 else
608 printf("\t, 0\n");
609
610 if (CDecl->getNumReferencedProtocols() > 0)
611 printf("\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_%s\n",
612 FullCategoryName);
613 else
614 printf("\t, 0\n");
Fariborz Jahanian1a0965e2007-10-24 21:25:12 +0000615 printf("\t, sizeof(struct _objc_category), 0\n};\n");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000616}
617
618//===----------------------------------------------------------------------===//
619// Meta Data Emission
620//===----------------------------------------------------------------------===//
621
622void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl) {
623 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
624
625 // Build _objc_ivar_list metadata for classes ivars if needed
626 int NumIvars = IDecl->getImplDeclNumIvars() > 0
627 ? IDecl->getImplDeclNumIvars()
628 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
629
630 if (NumIvars > 0) {
631 static bool objc_ivar = false;
632 if (!objc_ivar) {
633 /* struct _objc_ivar {
634 char *ivar_name;
635 char *ivar_type;
636 int ivar_offset;
637 };
638 */
639 printf("\nstruct _objc_ivar {\n");
640 printf("\tchar *ivar_name;\n");
641 printf("\tchar *ivar_type;\n");
642 printf("\tint ivar_offset;\n");
643 printf("};\n");
644 objc_ivar = true;
645 }
646
647 /* struct _objc_ivar_list {
648 int ivar_count;
649 struct _objc_ivar ivar_list[ivar_count];
650 };
651 */
652 printf("\nstatic struct {\n");
653 printf("\tint ivar_count;\n");
654 printf("\tstruct _objc_ivar ivar_list[%d];\n", NumIvars);
655 printf("} _OBJC_INSTANCE_VARIABLES_%s "
656 "__attribute__ ((section (\"__OBJC, __instance_vars\")))= "
657 "{\n\t%d\n",IDecl->getName(),
658 NumIvars);
659 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
660 ? IDecl->getImplDeclIVars()
661 : CDecl->getIntfDeclIvars();
662 for (int i = 0; i < NumIvars; i++)
663 // TODO: 1) ivar names may have to go to another section. 2) encode
664 // ivar_type type of each ivar . 3) compute and add ivar offset.
665 printf("\t,\"%s\", \"\", 0\n", Ivars[i]->getName());
666 printf("};\n");
667 }
668
669 // Build _objc_method_list for class's instance methods if needed
670 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
671 IDecl->getNumInstanceMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000672 true,
673 "", IDecl->getName());
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000674
675 // Build _objc_method_list for class's class methods if needed
676 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000677 IDecl->getNumClassMethods(),
678 false,
679 "", IDecl->getName());
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000680
681 // Protocols referenced in class declaration?
682 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
683 CDecl->getNumIntfRefProtocols(),
684 "CLASS",
685 CDecl->getName());
686
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000687
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000688 // Declaration of class/meta-class metadata
689 /* struct _objc_class {
690 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000691 const char *super_class_name;
692 char *name;
693 long version;
694 long info;
695 long instance_size;
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000696 struct _objc_ivar_list *ivars;
697 struct _objc_method_list *methods;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000698 struct objc_cache *cache;
699 struct objc_protocol_list *protocols;
700 const char *ivar_layout;
701 struct _objc_class_ext *ext;
702 };
703 */
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000704 static bool objc_class = false;
705 if (!objc_class) {
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000706 printf("\nstruct _objc_class {\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000707 printf("\tstruct _objc_class *isa;\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000708 printf("\tconst char *super_class_name;\n");
709 printf("\tchar *name;\n");
710 printf("\tlong version;\n");
711 printf("\tlong info;\n");
712 printf("\tlong instance_size;\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000713 printf("\tstruct _objc_ivar_list *ivars;\n");
714 printf("\tstruct _objc_method_list *methods;\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000715 printf("\tstruct objc_cache *cache;\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000716 printf("\tstruct _objc_protocol_list *protocols;\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000717 printf("\tconst char *ivar_layout;\n");
718 printf("\tstruct _objc_class_ext *ext;\n");
719 printf("};\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000720 objc_class = true;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000721 }
722
723 // Meta-class metadata generation.
724 ObjcInterfaceDecl *RootClass = 0;
725 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
726 while (SuperClass) {
727 RootClass = SuperClass;
728 SuperClass = SuperClass->getSuperClass();
729 }
730 SuperClass = CDecl->getSuperClass();
731
732 printf("\nstatic struct _objc_class _OBJC_METACLASS_%s "
733 "__attribute__ ((section (\"__OBJC, __meta_class\")))= "
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000734 "{\n\t(struct _objc_class *)\"%s\"",
735 CDecl->getName(), RootClass ? RootClass->getName()
736 : CDecl->getName());
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000737 if (SuperClass)
738 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
739 else
740 printf(", 0, \"%s\"", CDecl->getName());
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000741 // TODO: 'ivars' field for root class is currently set to 0.
742 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahanian1a0965e2007-10-24 21:25:12 +0000743 printf(", 0,2, sizeof(struct _objc_class), 0");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000744 if (CDecl->getNumClassMethods() > 0)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000745 printf("\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_%s\n",
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000746 CDecl->getName());
747 else
748 printf(", 0\n");
Fariborz Jahanian454cb012007-10-24 20:54:23 +0000749 if (CDecl->getNumIntfRefProtocols() > 0)
750 printf("\t,0,(struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_%s,0,0\n",
751 CDecl->getName());
752 else
753 printf("\t,0,0,0,0\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000754 printf("};\n");
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000755
756 // class metadata generation.
757 printf("\nstatic struct _objc_class _OBJC_CLASS_%s "
758 "__attribute__ ((section (\"__OBJC, __class\")))= "
759 "{\n\t&_OBJC_METACLASS_%s", CDecl->getName(), CDecl->getName());
760 if (SuperClass)
761 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
762 else
763 printf(", 0, \"%s\"", CDecl->getName());
764 // 'info' field is initialized to CLS_CLASS(1) for class
765 // TODO: instance_size is curently set to 0.
766 printf(", 0,1,0");
767 if (NumIvars > 0)
768 printf(", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_%s\n\t",
769 CDecl->getName());
770 else
771 printf(",0");
772 if (IDecl->getNumInstanceMethods() > 0)
773 printf(", (struct _objc_method_list*)&_OBJC_INSTANCE_METHODS_%s, 0\n\t",
774 CDecl->getName());
775 else
776 printf(",0,0");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000777 if (CDecl->getNumIntfRefProtocols() > 0)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000778 printf(", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_%s, 0,0\n",
779 CDecl->getName());
780 else
781 printf(",0,0,0\n");
782 printf("};\n");
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000783}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000784
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000785void RewriteTest::WriteObjcMetaData() {
786 int ClsDefCount = ClassImplementation.size();
787 int CatDefCount = CategoryImplementation.size();
788 if (ClsDefCount == 0 && CatDefCount == 0)
789 return;
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000790
Fariborz Jahanian454cb012007-10-24 20:54:23 +0000791 // TODO: This is temporary until we decide how to access objc types in a
792 // c program
793 printf("\n#include <Objc/objc.h>\n");
794
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000795 // For each implemented class, write out all its meta data.
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000796 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000797 RewriteObjcClassMetaData(ClassImplementation[i]);
798
799 // For each implemented category, write out all its meta data.
800 for (int i = 0; i < CatDefCount; i++)
801 RewriteObjcCategoryImplDecl(CategoryImplementation[i]);
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000802
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000803 // Write objc_symtab metadata
804 /*
805 struct _objc_symtab
806 {
807 long sel_ref_cnt;
808 SEL *refs;
809 short cls_def_cnt;
810 short cat_def_cnt;
811 void *defs[cls_def_cnt + cat_def_cnt];
812 };
813 */
814
815 printf("\nstruct _objc_symtab {\n");
816 printf("\tlong sel_ref_cnt;\n");
817 printf("\tSEL *refs;\n");
818 printf("\tshort cls_def_cnt;\n");
819 printf("\tshort cat_def_cnt;\n");
820 printf("\tvoid *defs[%d];\n", ClsDefCount + CatDefCount);
821 printf("};\n\n");
822
823 printf("static struct _objc_symtab "
Chris Lattnerf04da132007-10-24 17:06:59 +0000824 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n");
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000825 printf("\t0, 0, %d, %d\n", ClsDefCount, CatDefCount);
826 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000827 printf("\t,&_OBJC_CLASS_%s\n", ClassImplementation[i]->getName());
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000828
829 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000830 printf("\t,&_OBJC_CATEGORY_%s_%s\n",
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000831 CategoryImplementation[i]->getClassInterface()->getName(),
832 CategoryImplementation[i]->getName());
833
834 printf("};\n\n");
835
836 // Write objc_module metadata
837
838 /*
839 struct _objc_module {
840 long version;
841 long size;
842 const char *name;
843 struct _objc_symtab *symtab;
844 }
845 */
846
847 printf("\nstruct _objc_module {\n");
848 printf("\tlong version;\n");
849 printf("\tlong size;\n");
850 printf("\tconst char *name;\n");
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000851 printf("\tstruct _objc_symtab *symtab;\n");
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000852 printf("};\n\n");
853 printf("static struct _objc_module "
854 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n");
Fariborz Jahanian1a0965e2007-10-24 21:25:12 +0000855 printf("\t%d, sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n", OBJC_ABI_VERSION);
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000856 printf("};\n\n");
857}
Chris Lattner311ff022007-10-16 22:36:42 +0000858