blob: 3e1c3d799b73fc8fe0f460301b34241c724a9b14 [file] [log] [blame]
Chris Lattnerb429ae42007-10-11 00:43:27 +00001//===--- RewriteTest.cpp - Playground for the code rewriter ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Hacks and fun related to the code rewriter.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ASTConsumers.h"
Chris Lattner569faa62007-10-11 18:38:32 +000015#include "clang/Rewrite/Rewriter.h"
Chris Lattnerb429ae42007-10-11 00:43:27 +000016#include "clang/AST/AST.h"
17#include "clang/AST/ASTConsumer.h"
Chris Lattner569faa62007-10-11 18:38:32 +000018#include "clang/Basic/SourceManager.h"
Steve Naroffe9780582007-10-23 23:50:29 +000019#include "clang/Basic/IdentifierTable.h"
Chris Lattnerc3aa5c42007-10-25 17:07:24 +000020#include "llvm/ADT/StringExtras.h"
Chris Lattnerb429ae42007-10-11 00:43:27 +000021using namespace clang;
Chris Lattnerc3aa5c42007-10-25 17:07:24 +000022using llvm::utostr;
Chris Lattnerb429ae42007-10-11 00:43:27 +000023
Chris Lattnerb429ae42007-10-11 00:43:27 +000024namespace {
Chris Lattner569faa62007-10-11 18:38:32 +000025 class RewriteTest : public ASTConsumer {
Chris Lattner74db1682007-10-16 21:07:07 +000026 Rewriter Rewrite;
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000027 ASTContext *Context;
Chris Lattnerb429ae42007-10-11 00:43:27 +000028 SourceManager *SM;
Chris Lattner569faa62007-10-11 18:38:32 +000029 unsigned MainFileID;
Chris Lattner74db1682007-10-16 21:07:07 +000030 SourceLocation LastIncLoc;
Fariborz Jahanian640a01f2007-10-18 19:23:00 +000031 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
32 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Steve Naroffe9780582007-10-23 23:50:29 +000033
34 FunctionDecl *MsgSendFunctionDecl;
35 FunctionDecl *GetClassFunctionDecl;
Steve Naroff71226032007-10-24 22:48:43 +000036 FunctionDecl *SelGetUidFunctionDecl;
Steve Naroffe9780582007-10-23 23:50:29 +000037
Fariborz Jahanian640a01f2007-10-18 19:23:00 +000038 static const int OBJC_ABI_VERSION =7 ;
Chris Lattnerb429ae42007-10-11 00:43:27 +000039 public:
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000040 void Initialize(ASTContext &context, unsigned mainFileID) {
41 Context = &context;
42 SM = &Context->SourceMgr;
Chris Lattner569faa62007-10-11 18:38:32 +000043 MainFileID = mainFileID;
Steve Naroffe9780582007-10-23 23:50:29 +000044 MsgSendFunctionDecl = 0;
Steve Naroff95b28c12007-10-24 01:09:48 +000045 GetClassFunctionDecl = 0;
Steve Naroff71226032007-10-24 22:48:43 +000046 SelGetUidFunctionDecl = 0;
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000047 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattnerb429ae42007-10-11 00:43:27 +000048 }
Chris Lattner569faa62007-10-11 18:38:32 +000049
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000050 // Top Level Driver code.
51 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner74db1682007-10-16 21:07:07 +000052 void HandleDeclInMainFile(Decl *D);
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000053 ~RewriteTest();
54
55 // Syntactic Rewriting.
Chris Lattner74db1682007-10-16 21:07:07 +000056 void RewriteInclude(SourceLocation Loc);
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000057 void RewriteTabs();
58 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Chris Lattner6fe8b272007-10-16 22:36:42 +000059
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000060 // Expression Rewriting.
Chris Lattner0021f452007-10-24 16:57:36 +000061 Stmt *RewriteFunctionBody(Stmt *S);
62 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
63 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroff71226032007-10-24 22:48:43 +000064 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
65 Expr **args, unsigned nargs);
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000066 // Metadata emission.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +000067 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
68 std::string &Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +000069
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +000070 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl,
71 std::string &Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +000072
73 void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
74 int NumMethods,
Fariborz Jahaniana3986372007-10-25 00:14:44 +000075 bool IsInstanceMethod,
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +000076 const char *prefix,
Chris Lattnerc3aa5c42007-10-25 17:07:24 +000077 const char *ClassName,
78 std::string &Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +000079
80 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
81 int NumProtocols,
82 const char *prefix,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +000083 const char *ClassName,
84 std::string &Result);
85 void WriteObjcMetaData(std::string &Result);
Chris Lattnerb429ae42007-10-11 00:43:27 +000086 };
87}
88
Chris Lattner569faa62007-10-11 18:38:32 +000089ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattnerb429ae42007-10-11 00:43:27 +000090
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000091//===----------------------------------------------------------------------===//
92// Top Level Driver Code
93//===----------------------------------------------------------------------===//
94
Chris Lattner569faa62007-10-11 18:38:32 +000095void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner74db1682007-10-16 21:07:07 +000096 // Two cases: either the decl could be in the main file, or it could be in a
97 // #included file. If the former, rewrite it now. If the later, check to see
98 // if we rewrote the #include/#import.
99 SourceLocation Loc = D->getLocation();
100 Loc = SM->getLogicalLoc(Loc);
101
102 // If this is for a builtin, ignore it.
103 if (Loc.isInvalid()) return;
104
Steve Naroffe9780582007-10-23 23:50:29 +0000105 // Look for built-in declarations that we need to refer during the rewrite.
106 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroff95b28c12007-10-24 01:09:48 +0000107 if (strcmp(FD->getName(), "objc_msgSend") == 0)
Steve Naroffe9780582007-10-23 23:50:29 +0000108 MsgSendFunctionDecl = FD;
Steve Naroff95b28c12007-10-24 01:09:48 +0000109 else if (strcmp(FD->getName(), "objc_getClass") == 0)
Steve Naroffe9780582007-10-23 23:50:29 +0000110 GetClassFunctionDecl = FD;
Steve Naroff71226032007-10-24 22:48:43 +0000111 else if (strcmp(FD->getName(), "sel_getUid") == 0)
112 SelGetUidFunctionDecl = FD;
Steve Naroffe9780582007-10-23 23:50:29 +0000113 }
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000114
115 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner74db1682007-10-16 21:07:07 +0000116 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
117 return HandleDeclInMainFile(D);
118
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000119 // Otherwise, see if there is a #import in the main file that should be
120 // rewritten.
Chris Lattner74db1682007-10-16 21:07:07 +0000121 RewriteInclude(Loc);
122}
123
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000124/// HandleDeclInMainFile - This is called for each top-level decl defined in the
125/// main file of the input.
126void RewriteTest::HandleDeclInMainFile(Decl *D) {
127 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
128 if (Stmt *Body = FD->getBody())
129 FD->setBody(RewriteFunctionBody(Body));
130
131 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
132 ClassImplementation.push_back(CI);
133 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
134 CategoryImplementation.push_back(CI);
135 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
136 RewriteForwardClassDecl(CD);
137 // Nothing yet.
138}
139
140RewriteTest::~RewriteTest() {
141 // Get the top-level buffer that this corresponds to.
142 RewriteTabs();
143
144 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
145 // we are done.
146 if (const RewriteBuffer *RewriteBuf =
147 Rewrite.getRewriteBufferFor(MainFileID)) {
148 printf("Changed:\n");
149 std::string S(RewriteBuf->begin(), RewriteBuf->end());
150 printf("%s\n", S.c_str());
151 } else {
152 printf("No changes\n");
153 }
154
155 // Rewrite Objective-c meta data*
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000156 std::string ResultStr;
157 WriteObjcMetaData(ResultStr);
158 // For now just print the string out.
159 printf("%s", ResultStr.c_str());
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000160}
161
162//===----------------------------------------------------------------------===//
163// Syntactic (non-AST) Rewriting Code
164//===----------------------------------------------------------------------===//
165
Chris Lattner74db1682007-10-16 21:07:07 +0000166void RewriteTest::RewriteInclude(SourceLocation Loc) {
167 // Rip up the #include stack to the main file.
168 SourceLocation IncLoc = Loc, NextLoc = Loc;
169 do {
170 IncLoc = Loc;
171 Loc = SM->getLogicalLoc(NextLoc);
172 NextLoc = SM->getIncludeLoc(Loc);
173 } while (!NextLoc.isInvalid());
174
175 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
176 // IncLoc indicates the header that was included if it is useful.
177 IncLoc = SM->getLogicalLoc(IncLoc);
178 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
179 Loc == LastIncLoc)
180 return;
181 LastIncLoc = Loc;
182
183 unsigned IncCol = SM->getColumnNumber(Loc);
184 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
185
186 // Replace the #import with #include.
187 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
188}
189
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000190void RewriteTest::RewriteTabs() {
191 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
192 const char *MainBufStart = MainBuf.first;
193 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000194
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000195 // Loop over the whole file, looking for tabs.
196 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
197 if (*BufPtr != '\t')
198 continue;
199
200 // Okay, we found a tab. This tab will turn into at least one character,
201 // but it depends on which 'virtual column' it is in. Compute that now.
202 unsigned VCol = 0;
203 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
204 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
205 ++VCol;
206
207 // Okay, now that we know the virtual column, we know how many spaces to
208 // insert. We assume 8-character tab-stops.
209 unsigned Spaces = 8-(VCol & 7);
210
211 // Get the location of the tab.
212 SourceLocation TabLoc =
213 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
214
215 // Rewrite the single tab character into a sequence of spaces.
216 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
217 }
Chris Lattner569faa62007-10-11 18:38:32 +0000218}
219
220
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000221void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
222 int numDecls = ClassDecl->getNumForwardDecls();
223 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
224
225 // Get the start location and compute the semi location.
226 SourceLocation startLoc = ClassDecl->getLocation();
227 const char *startBuf = SM->getCharacterData(startLoc);
228 const char *semiPtr = strchr(startBuf, ';');
229
230 // Translate to typedef's that forward reference structs with the same name
231 // as the class. As a convenience, we include the original declaration
232 // as a comment.
233 std::string typedefString;
234 typedefString += "// ";
Steve Naroff71226032007-10-24 22:48:43 +0000235 typedefString.append(startBuf, semiPtr-startBuf+1);
236 typedefString += "\n";
237 for (int i = 0; i < numDecls; i++) {
238 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
239 typedefString += "typedef struct ";
240 typedefString += ForwardDecl->getName();
241 typedefString += " ";
242 typedefString += ForwardDecl->getName();
243 typedefString += ";\n";
244 }
245
246 // Replace the @class with typedefs corresponding to the classes.
247 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
248 typedefString.c_str(), typedefString.size());
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000249}
250
251//===----------------------------------------------------------------------===//
252// Function Body / Expression rewriting
253//===----------------------------------------------------------------------===//
254
Chris Lattner0021f452007-10-24 16:57:36 +0000255Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner6fe8b272007-10-16 22:36:42 +0000256 // Otherwise, just rewrite all children.
257 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
258 CI != E; ++CI)
Chris Lattnere33506b2007-10-17 21:28:00 +0000259 if (*CI)
Chris Lattner0021f452007-10-24 16:57:36 +0000260 *CI = RewriteFunctionBody(*CI);
Steve Naroffe9780582007-10-23 23:50:29 +0000261
262 // Handle specific things.
263 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
264 return RewriteAtEncode(AtEncode);
265
Steve Naroff71226032007-10-24 22:48:43 +0000266 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
267 // Before we rewrite it, put the original message expression in a comment.
268 SourceLocation startLoc = MessExpr->getLocStart();
269 SourceLocation endLoc = MessExpr->getLocEnd();
270
271 const char *startBuf = SM->getCharacterData(startLoc);
272 const char *endBuf = SM->getCharacterData(endLoc);
273
274 std::string messString;
275 messString += "// ";
276 messString.append(startBuf, endBuf-startBuf+1);
277 messString += "\n";
278
279 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
280 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
281 // Tried this, but it didn't work either...
282 // Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffe9780582007-10-23 23:50:29 +0000283 return RewriteMessageExpr(MessExpr);
Steve Naroff71226032007-10-24 22:48:43 +0000284 }
Chris Lattner0021f452007-10-24 16:57:36 +0000285 // Return this stmt unmodified.
286 return S;
Chris Lattner6fe8b272007-10-16 22:36:42 +0000287}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000288
Chris Lattner0021f452007-10-24 16:57:36 +0000289Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattnerbf0bfa62007-10-17 22:35:30 +0000290 // Create a new string expression.
291 QualType StrType = Context->getPointerType(Context->CharTy);
292 Expr *Replacement = new StringLiteral("foo", 3, false, StrType,
293 SourceLocation(), SourceLocation());
294 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattner0021f452007-10-24 16:57:36 +0000295 delete Exp;
296 return Replacement;
Chris Lattner6fe8b272007-10-16 22:36:42 +0000297}
298
Steve Naroff71226032007-10-24 22:48:43 +0000299CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
300 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffe9780582007-10-23 23:50:29 +0000301 // Get the type, we will need to reference it in a couple spots.
Steve Naroff71226032007-10-24 22:48:43 +0000302 QualType msgSendType = FD->getType();
Steve Naroffe9780582007-10-23 23:50:29 +0000303
304 // Create a reference to the objc_msgSend() declaration.
Steve Naroff71226032007-10-24 22:48:43 +0000305 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffe9780582007-10-23 23:50:29 +0000306
307 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000308 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffe9780582007-10-23 23:50:29 +0000309 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
310
311 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattner0021f452007-10-24 16:57:36 +0000312
Steve Naroff71226032007-10-24 22:48:43 +0000313 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
314}
315
316Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
317 assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
318 assert(SelGetUidFunctionDecl && "Can't find sel_getUid() decl");
319 assert(GetClassFunctionDecl && "Can't find objc_getClass() decl");
320
321 // Synthesize a call to objc_msgSend().
322 llvm::SmallVector<Expr*, 8> MsgExprs;
323 IdentifierInfo *clsName = Exp->getClassName();
324
325 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
326 if (clsName) { // class message.
327 llvm::SmallVector<Expr*, 8> ClsExprs;
328 QualType argType = Context->getPointerType(Context->CharTy);
329 ClsExprs.push_back(new StringLiteral(clsName->getName(),
330 clsName->getLength(),
331 false, argType, SourceLocation(),
332 SourceLocation()));
333 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
334 &ClsExprs[0], ClsExprs.size());
335 MsgExprs.push_back(Cls);
336 } else // instance message.
337 MsgExprs.push_back(Exp->getReceiver());
338
339 // Create a call to sel_getUid("selName"), it will be the 2nd argument.
340 llvm::SmallVector<Expr*, 8> SelExprs;
341 QualType argType = Context->getPointerType(Context->CharTy);
342 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
343 Exp->getSelector().getName().size(),
344 false, argType, SourceLocation(),
345 SourceLocation()));
346 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
347 &SelExprs[0], SelExprs.size());
348 MsgExprs.push_back(SelExp);
349
350 // Now push any user supplied arguments.
351 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
352 MsgExprs.push_back(Exp->getArg(i));
353 // We've transferred the ownership to MsgExprs. Null out the argument in
354 // the original expression, since we will delete it below.
355 Exp->setArg(i, 0);
356 }
357 CallExpr *MessExp = SynthesizeCallToFunctionDecl(MsgSendFunctionDecl,
358 &MsgExprs[0], MsgExprs.size());
359 // Now do the actual rewrite.
360 Rewrite.ReplaceStmt(Exp, MessExp);
361
Chris Lattner0021f452007-10-24 16:57:36 +0000362 delete Exp;
Steve Naroff71226032007-10-24 22:48:43 +0000363 return MessExp;
Steve Naroffe9780582007-10-23 23:50:29 +0000364}
365
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000366// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
367/// class methods.
368void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
369 int NumMethods,
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000370 bool IsInstanceMethod,
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000371 const char *prefix,
Chris Lattnerc3aa5c42007-10-25 17:07:24 +0000372 const char *ClassName,
373 std::string &Result) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000374 static bool objc_impl_method = false;
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000375 if (NumMethods > 0 && !objc_impl_method) {
376 /* struct _objc_method {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000377 SEL _cmd;
378 char *method_types;
379 void *_imp;
380 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000381 */
Chris Lattnerc3aa5c42007-10-25 17:07:24 +0000382 Result += "\nstruct _objc_method {\n";
383 Result += "\tSEL _cmd;\n";
384 Result += "\tchar *method_types;\n";
385 Result += "\tvoid *_imp;\n";
386 Result += "};\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000387
388 /* struct _objc_method_list {
389 struct _objc_method_list *next_method;
390 int method_count;
391 struct _objc_method method_list[];
392 }
393 */
394 Result += "\nstruct _objc_method_list {\n";
395 Result += "\tstruct _objc_method_list *next_method;\n";
396 Result += "\tint method_count;\n";
397 Result += "\tstruct _objc_method method_list[];\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000398 objc_impl_method = true;
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000399 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000400 // Build _objc_method_list for class's methods if needed
401 if (NumMethods > 0) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000402 Result += "\nstatic struct _objc_method_list _OBJC_";
Chris Lattnerc3aa5c42007-10-25 17:07:24 +0000403 Result += prefix;
404 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
405 Result += "_METHODS_";
406 Result += ClassName;
407 Result += " __attribute__ ((section (\"__OBJC, __";
408 Result += IsInstanceMethod ? "inst" : "cls";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000409 Result += "_meth\")))= ";
410 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
411
412 Result += "\t,{{(SEL)\"";
413 Result += Methods[0]->getSelector().getName().c_str();
414 Result += "\", \"\", 0}\n";
415
416 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000417 // TODO: 1) method selector name may hav to go into their own section
418 // 2) encode method types for use here (which may have to go into
419 // __meth_var_types section, 3) Need method address as 3rd initializer.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000420 Result += "\t ,{(SEL)\"";
421 Result += Methods[i]->getSelector().getName().c_str();
422 Result += "\", \"\", 0}\n";
423 }
424 Result += "\t }\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000425 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000426}
427
428/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
429void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
430 int NumProtocols,
431 const char *prefix,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000432 const char *ClassName,
433 std::string &Result) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000434 static bool objc_protocol_methods = false;
Fariborz Jahanian04455192007-10-22 21:41:37 +0000435 if (NumProtocols > 0) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000436 for (int i = 0; i < NumProtocols; i++) {
437 ObjcProtocolDecl *PDecl = Protocols[i];
438 // Output struct protocol_methods holder of method selector and type.
439 if (!objc_protocol_methods &&
440 (PDecl->getNumInstanceMethods() > 0
441 || PDecl->getNumClassMethods() > 0)) {
442 /* struct protocol_methods {
443 SEL _cmd;
444 char *method_types;
445 }
446 */
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000447 Result += "\nstruct protocol_methods {\n";
448 Result += "\tSEL _cmd;\n";
449 Result += "\tchar *method_types;\n";
450 Result += "};\n";
451
452 /* struct _objc_protocol_method_list {
453 int protocol_method_count;
454 struct protocol_methods protocols[];
455 }
456 */
457 Result += "\nstruct _objc_protocol_method_list {\n";
458 Result += "\tint protocol_method_count;\n";
459 Result += "\tstruct protocol_methods protocols[];\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000460 objc_protocol_methods = true;
461 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000462
Fariborz Jahanian04455192007-10-22 21:41:37 +0000463 // Output instance methods declared in this protocol.
Fariborz Jahanian04455192007-10-22 21:41:37 +0000464 int NumMethods = PDecl->getNumInstanceMethods();
465 if (NumMethods > 0) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000466 Result += "\nstatic struct _objc_protocol_method_list "
467 "_OBJC_PROTOCOL_INSTANCE_METHODS_";
468 Result += PDecl->getName();
469 Result += " __attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
470 "{\n\t" + utostr(NumMethods) + "\n";
471
Fariborz Jahanian04455192007-10-22 21:41:37 +0000472 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000473 Result += "\t,{{(SEL)\"";
474 Result += Methods[0]->getSelector().getName().c_str();
475 Result += "\", \"\"}\n";
476
477 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000478 // TODO: 1) method selector name may hav to go into their own section
479 // 2) encode method types for use here (which may have to go into
480 // __meth_var_types section.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000481 Result += "\t ,{(SEL)\"";
482 Result += Methods[i]->getSelector().getName().c_str();
483 Result += "\", \"\"}\n";
484 }
485 Result += "\t }\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000486 }
487
488 // Output class methods declared in this protocol.
489 NumMethods = PDecl->getNumClassMethods();
490 if (NumMethods > 0) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000491 Result += "\nstatic struct _objc_protocol_method_list "
492 "_OBJC_PROTOCOL_CLASS_METHODS_";
493 Result += PDecl->getName();
494 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
495 "{\n\t";
496 Result += utostr(NumMethods);
497 Result += "\n";
498
Fariborz Jahanian04455192007-10-22 21:41:37 +0000499 ObjcMethodDecl **Methods = PDecl->getClassMethods();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000500 Result += "\t,{{(SEL)\"";
501 Result += Methods[0]->getSelector().getName().c_str();
502 Result += "\", \"\"}\n";
503
504 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000505 // TODO: 1) method selector name may hav to go into their own section
506 // 2) encode method types for use here (which may have to go into
507 // __meth_var_types section.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000508 Result += "\t ,{(SEL)\"";
509 Result += Methods[i]->getSelector().getName().c_str();
510 Result += "\", \"\"}\n";
511 }
512 Result += "\t }\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000513 }
514 // Output:
515 /* struct _objc_protocol {
516 // Objective-C 1.0 extensions
517 struct _objc_protocol_extension *isa;
518 char *protocol_name;
519 struct _objc_protocol **protocol_list;
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000520 struct _objc_protocol_method_list *instance_methods;
521 struct _objc_protocol_method_list *class_methods;
Fariborz Jahanian04455192007-10-22 21:41:37 +0000522 };
523 */
524 static bool objc_protocol = false;
525 if (!objc_protocol) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000526 Result += "\nstruct _objc_protocol {\n";
527 Result += "\tstruct _objc_protocol_extension *isa;\n";
528 Result += "\tchar *protocol_name;\n";
529 Result += "\tstruct _objc_protocol **protocol_list;\n";
530 Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
531 Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
532 Result += "};\n";
533
534 /* struct _objc_protocol_list {
535 struct _objc_protocol_list *next;
536 int protocol_count;
537 struct _objc_protocol *class_protocols[];
538 }
539 */
540 Result += "\nstruct _objc_protocol_list {\n";
541 Result += "\tstruct _objc_protocol_list *next;\n";
542 Result += "\tint protocol_count;\n";
543 Result += "\tstruct _objc_protocol *class_protocols[];\n";
544 Result += "};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000545 objc_protocol = true;
546 }
547
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000548 Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
549 Result += PDecl->getName();
550 Result += " __attribute__ ((section (\"__OBJC, __protocol\")))= "
551 "{\n\t0, \"";
552 Result += PDecl->getName();
553 Result += "\", 0, ";
554 if (PDecl->getInstanceMethods() > 0) {
555 Result += "&_OBJC_PROTOCOL_INSTANCE_METHODS_";
556 Result += PDecl->getName();
557 Result += ", ";
558 }
Fariborz Jahanian04455192007-10-22 21:41:37 +0000559 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000560 Result += "0, ";
561 if (PDecl->getClassMethods() > 0) {
562 Result += "&_OBJC_PROTOCOL_CLASS_METHODS_";
563 Result += PDecl->getName();
564 Result += "\n";
565 }
Fariborz Jahanian04455192007-10-22 21:41:37 +0000566 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000567 Result += "0\n";
568 Result += "};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000569 }
Fariborz Jahanian04455192007-10-22 21:41:37 +0000570 // Output the top lovel protocol meta-data for the class.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000571 Result += "\nstatic struct _objc_protocol_list _OBJC_";
572 Result += prefix;
573 Result += "_PROTOCOLS_";
574 Result += ClassName;
575 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
576 "{\n\t0, ";
577 Result += utostr(NumProtocols);
578 Result += "\n";
579
580 Result += "\t,{&_OBJC_PROTOCOL_";
581 Result += Protocols[0]->getName();
582 Result += " \n";
583
584 for (int i = 1; i < NumProtocols; i++) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000585 ObjcProtocolDecl *PDecl = Protocols[i];
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000586 Result += "\t ,&_OBJC_PROTOCOL_";
587 Result += PDecl->getName();
588 Result += "\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000589 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000590 Result += "\t }\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000591 }
592}
593
594/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
595/// implementation.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000596void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl,
597 std::string &Result) {
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000598 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
599 // Find category declaration for this implementation.
600 ObjcCategoryDecl *CDecl;
601 for (CDecl = ClassDecl->getCategoryList(); CDecl;
602 CDecl = CDecl->getNextClassCategory())
603 if (CDecl->getIdentifier() == IDecl->getIdentifier())
604 break;
605 assert(CDecl && "RewriteObjcCategoryImplDecl - bad category");
606
607 char *FullCategoryName = (char*)alloca(
608 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
609 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
610
611 // Build _objc_method_list for class's instance methods if needed
612 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
613 IDecl->getNumInstanceMethods(),
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000614 true,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000615 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000616
617 // Build _objc_method_list for class's class methods if needed
618 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
619 IDecl->getNumClassMethods(),
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000620 false,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000621 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000622
623 // Protocols referenced in class declaration?
624 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
625 CDecl->getNumReferencedProtocols(),
626 "CATEGORY",
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000627 FullCategoryName, Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000628
629 /* struct _objc_category {
630 char *category_name;
631 char *class_name;
632 struct _objc_method_list *instance_methods;
633 struct _objc_method_list *class_methods;
634 struct _objc_protocol_list *protocols;
635 // Objective-C 1.0 extensions
636 uint32_t size; // sizeof (struct _objc_category)
637 struct _objc_property_list *instance_properties; // category's own
638 // @property decl.
639 };
640 */
641
642 static bool objc_category = false;
643 if (!objc_category) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000644 Result += "\nstruct _objc_category {\n";
645 Result += "\tchar *category_name;\n";
646 Result += "\tchar *class_name;\n";
647 Result += "\tstruct _objc_method_list *instance_methods;\n";
648 Result += "\tstruct _objc_method_list *class_methods;\n";
649 Result += "\tstruct _objc_protocol_list *protocols;\n";
650 Result += "\tunsigned int size;\n";
651 Result += "\tstruct _objc_property_list *instance_properties;\n";
652 Result += "};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000653 objc_category = true;
Fariborz Jahanian04455192007-10-22 21:41:37 +0000654 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000655 Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
656 Result += FullCategoryName;
657 Result += " __attribute__ ((section (\"__OBJC, __category\")))= {\n\t\"";
658 Result += IDecl->getName();
659 Result += "\"\n\t, \"";
660 Result += ClassDecl->getName();
661 Result += "\"\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000662
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000663 if (IDecl->getNumInstanceMethods() > 0) {
664 Result += "\t, (struct _objc_method_list *)"
665 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
666 Result += FullCategoryName;
667 Result += "\n";
668 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000669 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000670 Result += "\t, 0\n";
671 if (IDecl->getNumClassMethods() > 0) {
672 Result += "\t, (struct _objc_method_list *)"
673 "&_OBJC_CATEGORY_CLASS_METHODS_";
674 Result += FullCategoryName;
675 Result += "\n";
676 }
677 else
678 Result += "\t, 0\n";
679
680 if (CDecl->getNumReferencedProtocols() > 0) {
681 Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
682 Result += FullCategoryName;
683 Result += "\n";
684 }
685 else
686 Result += "\t, 0\n";
687 Result += "\t, sizeof(struct _objc_category), 0\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000688}
689
690//===----------------------------------------------------------------------===//
691// Meta Data Emission
692//===----------------------------------------------------------------------===//
693
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000694void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
695 std::string &Result) {
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000696 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
697
698 // Build _objc_ivar_list metadata for classes ivars if needed
699 int NumIvars = IDecl->getImplDeclNumIvars() > 0
700 ? IDecl->getImplDeclNumIvars()
701 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
702
703 if (NumIvars > 0) {
704 static bool objc_ivar = false;
705 if (!objc_ivar) {
706 /* struct _objc_ivar {
707 char *ivar_name;
708 char *ivar_type;
709 int ivar_offset;
710 };
711 */
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000712 Result += "\nstruct _objc_ivar {\n";
713 Result += "\tchar *ivar_name;\n";
714 Result += "\tchar *ivar_type;\n";
715 Result += "\tint ivar_offset;\n";
716 Result += "};\n";
717
718 /* struct _objc_ivar_list {
719 int ivar_count;
720 struct _objc_ivar ivar_list[];
721 };
722 */
723 Result += "\nstruct _objc_ivar_list {\n";
724 Result += "\tint ivar_count;\n";
725 Result += "\tstruct _objc_ivar ivar_list[];\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000726 objc_ivar = true;
727 }
728
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000729 Result += "\nstatic struct _objc_ivar_list _OBJC_INSTANCE_VARIABLES_";
730 Result += IDecl->getName();
731 Result += " __attribute__ ((section (\"__OBJC, __instance_vars\")))= "
732 "{\n\t";
733 Result += utostr(NumIvars);
734 Result += "\n";
735
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000736 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
737 ? IDecl->getImplDeclIVars()
738 : CDecl->getIntfDeclIvars();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000739 Result += "\t,{{\"";
740 Result += Ivars[0]->getName();
741 Result += "\", \"\", 0}\n";
742 for (int i = 1; i < NumIvars; i++) {
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000743 // TODO: 1) ivar names may have to go to another section. 2) encode
744 // ivar_type type of each ivar . 3) compute and add ivar offset.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000745 Result += "\t ,{\"";
746 Result += Ivars[i]->getName();
747 Result += "\", \"\", 0}\n";
748 }
749
750 Result += "\t }\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000751 }
752
753 // Build _objc_method_list for class's instance methods if needed
754 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
755 IDecl->getNumInstanceMethods(),
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000756 true,
757 "", IDecl->getName(), Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000758
759 // Build _objc_method_list for class's class methods if needed
760 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000761 IDecl->getNumClassMethods(),
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000762 false,
763 "", IDecl->getName(), Result);
764
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000765 // Protocols referenced in class declaration?
766 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
767 CDecl->getNumIntfRefProtocols(),
768 "CLASS",
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000769 CDecl->getName(), Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000770
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000771
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000772 // Declaration of class/meta-class metadata
773 /* struct _objc_class {
774 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000775 const char *super_class_name;
776 char *name;
777 long version;
778 long info;
779 long instance_size;
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000780 struct _objc_ivar_list *ivars;
781 struct _objc_method_list *methods;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000782 struct objc_cache *cache;
783 struct objc_protocol_list *protocols;
784 const char *ivar_layout;
785 struct _objc_class_ext *ext;
786 };
787 */
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000788 static bool objc_class = false;
789 if (!objc_class) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000790 Result += "\nstruct _objc_class {\n";
791 Result += "\tstruct _objc_class *isa;\n";
792 Result += "\tconst char *super_class_name;\n";
793 Result += "\tchar *name;\n";
794 Result += "\tlong version;\n";
795 Result += "\tlong info;\n";
796 Result += "\tlong instance_size;\n";
797 Result += "\tstruct _objc_ivar_list *ivars;\n";
798 Result += "\tstruct _objc_method_list *methods;\n";
799 Result += "\tstruct objc_cache *cache;\n";
800 Result += "\tstruct _objc_protocol_list *protocols;\n";
801 Result += "\tconst char *ivar_layout;\n";
802 Result += "\tstruct _objc_class_ext *ext;\n";
803 Result += "};\n";
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000804 objc_class = true;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000805 }
806
807 // Meta-class metadata generation.
808 ObjcInterfaceDecl *RootClass = 0;
809 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
810 while (SuperClass) {
811 RootClass = SuperClass;
812 SuperClass = SuperClass->getSuperClass();
813 }
814 SuperClass = CDecl->getSuperClass();
815
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000816 Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
817 Result += CDecl->getName();
818 Result += " __attribute__ ((section (\"__OBJC, __meta_class\")))= "
819 "{\n\t(struct _objc_class *)\"";
820 Result += (RootClass ? RootClass->getName() : CDecl->getName());
821 Result += "\"";
822
823 if (SuperClass) {
824 Result += ", \"";
825 Result += SuperClass->getName();
826 Result += "\", \"";
827 Result += CDecl->getName();
828 Result += "\"";
829 }
830 else {
831 Result += ", 0, \"";
832 Result += CDecl->getName();
833 Result += "\"";
834 }
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000835 // TODO: 'ivars' field for root class is currently set to 0.
836 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000837 Result += ", 0,2, sizeof(struct _objc_class), 0";
838 if (CDecl->getNumClassMethods() > 0) {
839 Result += "\n\t, &_OBJC_CLASS_METHODS_";
840 Result += CDecl->getName();
841 Result += "\n";
842 }
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000843 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000844 Result += ", 0\n";
845 if (CDecl->getNumIntfRefProtocols() > 0) {
846 Result += "\t,0, &_OBJC_CLASS_PROTOCOLS_";
847 Result += CDecl->getName();
848 Result += ",0,0\n";
849 }
Fariborz Jahanian0cb4d922007-10-24 20:54:23 +0000850 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000851 Result += "\t,0,0,0,0\n";
852 Result += "};\n";
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000853
854 // class metadata generation.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000855 Result += "\nstatic struct _objc_class _OBJC_CLASS_";
856 Result += CDecl->getName();
857 Result += " __attribute__ ((section (\"__OBJC, __class\")))= "
858 "{\n\t&_OBJC_METACLASS_";
859 Result += CDecl->getName();
860 if (SuperClass) {
861 Result += ", \"";
862 Result += SuperClass->getName();
863 Result += "\", \"";
864 Result += CDecl->getName();
865 Result += "\"";
866 }
867 else {
868 Result += ", 0, \"";
869 Result += CDecl->getName();
870 Result += "\"";
871 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000872 // 'info' field is initialized to CLS_CLASS(1) for class
873 // TODO: instance_size is curently set to 0.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000874 Result += ", 0,1,0";
875 if (NumIvars > 0) {
876 Result += ", &_OBJC_INSTANCE_VARIABLES_";
877 Result += CDecl->getName();
878 Result += "\n\t";
879 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000880 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000881 Result += ",0";
882 if (IDecl->getNumInstanceMethods() > 0) {
883 Result += ", &_OBJC_INSTANCE_METHODS_";
884 Result += CDecl->getName();
885 Result += ", 0\n\t";
886 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000887 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000888 Result += ",0,0";
889 if (CDecl->getNumIntfRefProtocols() > 0) {
890 Result += ", &_OBJC_CLASS_PROTOCOLS_";
891 Result += CDecl->getName();
892 Result += ", 0,0\n";
893 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000894 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000895 Result += ",0,0,0\n";
896 Result += "};\n";
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000897}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000898
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000899void RewriteTest::WriteObjcMetaData(std::string &Result) {
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000900 int ClsDefCount = ClassImplementation.size();
901 int CatDefCount = CategoryImplementation.size();
902 if (ClsDefCount == 0 && CatDefCount == 0)
903 return;
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000904
Fariborz Jahanian0cb4d922007-10-24 20:54:23 +0000905 // TODO: This is temporary until we decide how to access objc types in a
906 // c program
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000907 Result += "\n#include <Objc/objc.h>\n";
Fariborz Jahanian0cb4d922007-10-24 20:54:23 +0000908
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000909 // For each implemented class, write out all its meta data.
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000910 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000911 RewriteObjcClassMetaData(ClassImplementation[i], Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000912
913 // For each implemented category, write out all its meta data.
914 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000915 RewriteObjcCategoryImplDecl(CategoryImplementation[i], Result);
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000916
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000917 // Write objc_symtab metadata
918 /*
919 struct _objc_symtab
920 {
921 long sel_ref_cnt;
922 SEL *refs;
923 short cls_def_cnt;
924 short cat_def_cnt;
925 void *defs[cls_def_cnt + cat_def_cnt];
926 };
927 */
928
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000929 Result += "\nstruct _objc_symtab {\n";
930 Result += "\tlong sel_ref_cnt;\n";
931 Result += "\tSEL *refs;\n";
932 Result += "\tshort cls_def_cnt;\n";
933 Result += "\tshort cat_def_cnt;\n";
934 Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
935 Result += "};\n\n";
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000936
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000937 Result += "static struct _objc_symtab "
938 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n";
939 Result += "\t0, 0, " + utostr(ClsDefCount)
940 + ", " + utostr(CatDefCount) + "\n";
941 for (int i = 0; i < ClsDefCount; i++) {
942 Result += "\t,&_OBJC_CLASS_";
943 Result += ClassImplementation[i]->getName();
944 Result += "\n";
945 }
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000946
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000947 for (int i = 0; i < CatDefCount; i++) {
948 Result += "\t,&_OBJC_CATEGORY_";
949 Result += CategoryImplementation[i]->getClassInterface()->getName();
950 Result += "_";
951 Result += CategoryImplementation[i]->getName();
952 Result += "\n";
953 }
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000954
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000955 Result += "};\n\n";
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000956
957 // Write objc_module metadata
958
959 /*
960 struct _objc_module {
961 long version;
962 long size;
963 const char *name;
964 struct _objc_symtab *symtab;
965 }
966 */
967
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000968 Result += "\nstruct _objc_module {\n";
969 Result += "\tlong version;\n";
970 Result += "\tlong size;\n";
971 Result += "\tconst char *name;\n";
972 Result += "\tstruct _objc_symtab *symtab;\n";
973 Result += "};\n\n";
974 Result += "static struct _objc_module "
975 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n";
976 Result += "\t" + utostr(OBJC_ABI_VERSION) + ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
977 Result += "};\n\n";
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000978}
Chris Lattner6fe8b272007-10-16 22:36:42 +0000979