blob: c76b9eeba9bb2115e9781f3d8ac773d8c975a152 [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"
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000021#include "llvm/ADT/SmallPtrSet.h"
Chris Lattner77cd2a02007-10-11 00:43:27 +000022using namespace clang;
Chris Lattner158ecb92007-10-25 17:07:24 +000023using llvm::utostr;
Chris Lattner77cd2a02007-10-11 00:43:27 +000024
Chris Lattner77cd2a02007-10-11 00:43:27 +000025namespace {
Chris Lattner8a12c272007-10-11 18:38:32 +000026 class RewriteTest : public ASTConsumer {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000027 Rewriter Rewrite;
Chris Lattner01c57482007-10-17 22:35:30 +000028 ASTContext *Context;
Chris Lattner77cd2a02007-10-11 00:43:27 +000029 SourceManager *SM;
Chris Lattner8a12c272007-10-11 18:38:32 +000030 unsigned MainFileID;
Chris Lattner2c64b7b2007-10-16 21:07:07 +000031 SourceLocation LastIncLoc;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000032 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
33 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000034 llvm::SmallPtrSet<ObjcInterfaceDecl*, 8> ObjcSynthesizedStructs;
Steve Naroffebf2b562007-10-23 23:50:29 +000035
36 FunctionDecl *MsgSendFunctionDecl;
37 FunctionDecl *GetClassFunctionDecl;
Steve Naroff934f2762007-10-24 22:48:43 +000038 FunctionDecl *SelGetUidFunctionDecl;
Steve Naroffebf2b562007-10-23 23:50:29 +000039
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000040 static const int OBJC_ABI_VERSION =7 ;
Chris Lattner77cd2a02007-10-11 00:43:27 +000041 public:
Chris Lattner01c57482007-10-17 22:35:30 +000042 void Initialize(ASTContext &context, unsigned mainFileID) {
43 Context = &context;
44 SM = &Context->SourceMgr;
Chris Lattner8a12c272007-10-11 18:38:32 +000045 MainFileID = mainFileID;
Steve Naroffebf2b562007-10-23 23:50:29 +000046 MsgSendFunctionDecl = 0;
Steve Naroffc0006092007-10-24 01:09:48 +000047 GetClassFunctionDecl = 0;
Steve Naroff934f2762007-10-24 22:48:43 +000048 SelGetUidFunctionDecl = 0;
Chris Lattner01c57482007-10-17 22:35:30 +000049 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattner77cd2a02007-10-11 00:43:27 +000050 }
Chris Lattner8a12c272007-10-11 18:38:32 +000051
Chris Lattnerf04da132007-10-24 17:06:59 +000052 // Top Level Driver code.
53 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner2c64b7b2007-10-16 21:07:07 +000054 void HandleDeclInMainFile(Decl *D);
Chris Lattnerf04da132007-10-24 17:06:59 +000055 ~RewriteTest();
56
57 // Syntactic Rewriting.
Chris Lattner2c64b7b2007-10-16 21:07:07 +000058 void RewriteInclude(SourceLocation Loc);
Chris Lattnerf04da132007-10-24 17:06:59 +000059 void RewriteTabs();
60 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Steve Naroffbef11852007-10-26 20:53:56 +000061 void RewriteInterfaceDecl(ObjcInterfaceDecl *Dcl);
Chris Lattner311ff022007-10-16 22:36:42 +000062
Chris Lattnerf04da132007-10-24 17:06:59 +000063 // Expression Rewriting.
Chris Lattnere64b7772007-10-24 16:57:36 +000064 Stmt *RewriteFunctionBody(Stmt *S);
65 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
66 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroff934f2762007-10-24 22:48:43 +000067 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
68 Expr **args, unsigned nargs);
Chris Lattnerf04da132007-10-24 17:06:59 +000069 // Metadata emission.
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000070 void HandleObjcMetaDataEmission();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000071 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
72 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000073
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000074 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl,
75 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000076
77 void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
78 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +000079 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000080 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +000081 const char *ClassName,
82 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000083
84 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
85 int NumProtocols,
86 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000087 const char *ClassName,
88 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000089 void SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
90 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000091 void SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
92 ObjcIvarDecl *ivar,
93 std::string &Result);
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000094 void WriteObjcMetaData(std::string &Result);
Chris Lattner77cd2a02007-10-11 00:43:27 +000095 };
96}
97
Chris Lattner8a12c272007-10-11 18:38:32 +000098ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattner77cd2a02007-10-11 00:43:27 +000099
Chris Lattnerf04da132007-10-24 17:06:59 +0000100//===----------------------------------------------------------------------===//
101// Top Level Driver Code
102//===----------------------------------------------------------------------===//
103
Chris Lattner8a12c272007-10-11 18:38:32 +0000104void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000105 // Two cases: either the decl could be in the main file, or it could be in a
106 // #included file. If the former, rewrite it now. If the later, check to see
107 // if we rewrote the #include/#import.
108 SourceLocation Loc = D->getLocation();
109 Loc = SM->getLogicalLoc(Loc);
110
111 // If this is for a builtin, ignore it.
112 if (Loc.isInvalid()) return;
113
Steve Naroffebf2b562007-10-23 23:50:29 +0000114 // Look for built-in declarations that we need to refer during the rewrite.
115 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroffc0006092007-10-24 01:09:48 +0000116 if (strcmp(FD->getName(), "objc_msgSend") == 0)
Steve Naroffebf2b562007-10-23 23:50:29 +0000117 MsgSendFunctionDecl = FD;
Steve Naroffc0006092007-10-24 01:09:48 +0000118 else if (strcmp(FD->getName(), "objc_getClass") == 0)
Steve Naroffebf2b562007-10-23 23:50:29 +0000119 GetClassFunctionDecl = FD;
Steve Naroff934f2762007-10-24 22:48:43 +0000120 else if (strcmp(FD->getName(), "sel_getUid") == 0)
121 SelGetUidFunctionDecl = FD;
Steve Naroffbef11852007-10-26 20:53:56 +0000122 } else if (ObjcInterfaceDecl *MD = dyn_cast<ObjcInterfaceDecl>(D)) {
123 RewriteInterfaceDecl(MD);
Steve Naroffebf2b562007-10-23 23:50:29 +0000124 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000125 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000126 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
127 return HandleDeclInMainFile(D);
128
Chris Lattnerf04da132007-10-24 17:06:59 +0000129 // Otherwise, see if there is a #import in the main file that should be
130 // rewritten.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000131 RewriteInclude(Loc);
132}
133
Chris Lattnerf04da132007-10-24 17:06:59 +0000134/// HandleDeclInMainFile - This is called for each top-level decl defined in the
135/// main file of the input.
136void RewriteTest::HandleDeclInMainFile(Decl *D) {
137 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
138 if (Stmt *Body = FD->getBody())
139 FD->setBody(RewriteFunctionBody(Body));
140
141 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
142 ClassImplementation.push_back(CI);
143 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
144 CategoryImplementation.push_back(CI);
145 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
146 RewriteForwardClassDecl(CD);
147 // Nothing yet.
148}
149
150RewriteTest::~RewriteTest() {
151 // Get the top-level buffer that this corresponds to.
152 RewriteTabs();
153
154 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
155 // we are done.
156 if (const RewriteBuffer *RewriteBuf =
157 Rewrite.getRewriteBufferFor(MainFileID)) {
158 printf("Changed:\n");
159 std::string S(RewriteBuf->begin(), RewriteBuf->end());
160 printf("%s\n", S.c_str());
161 } else {
162 printf("No changes\n");
163 }
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000164
165}
166
167/// HandleObjcMetaDataEmission - main routine to generate objective-c's
168/// metadata.
169void RewriteTest::HandleObjcMetaDataEmission() {
Chris Lattnerf04da132007-10-24 17:06:59 +0000170 // Rewrite Objective-c meta data*
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000171 std::string ResultStr;
172 WriteObjcMetaData(ResultStr);
173 // For now just print the string out.
174 printf("%s", ResultStr.c_str());
Chris Lattnerf04da132007-10-24 17:06:59 +0000175}
176
177//===----------------------------------------------------------------------===//
178// Syntactic (non-AST) Rewriting Code
179//===----------------------------------------------------------------------===//
180
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000181void RewriteTest::RewriteInclude(SourceLocation Loc) {
182 // Rip up the #include stack to the main file.
183 SourceLocation IncLoc = Loc, NextLoc = Loc;
184 do {
185 IncLoc = Loc;
186 Loc = SM->getLogicalLoc(NextLoc);
187 NextLoc = SM->getIncludeLoc(Loc);
188 } while (!NextLoc.isInvalid());
189
190 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
191 // IncLoc indicates the header that was included if it is useful.
192 IncLoc = SM->getLogicalLoc(IncLoc);
193 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
194 Loc == LastIncLoc)
195 return;
196 LastIncLoc = Loc;
197
198 unsigned IncCol = SM->getColumnNumber(Loc);
199 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
200
201 // Replace the #import with #include.
202 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
203}
204
Chris Lattnerf04da132007-10-24 17:06:59 +0000205void RewriteTest::RewriteTabs() {
206 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
207 const char *MainBufStart = MainBuf.first;
208 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000209
Chris Lattnerf04da132007-10-24 17:06:59 +0000210 // Loop over the whole file, looking for tabs.
211 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
212 if (*BufPtr != '\t')
213 continue;
214
215 // Okay, we found a tab. This tab will turn into at least one character,
216 // but it depends on which 'virtual column' it is in. Compute that now.
217 unsigned VCol = 0;
218 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
219 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
220 ++VCol;
221
222 // Okay, now that we know the virtual column, we know how many spaces to
223 // insert. We assume 8-character tab-stops.
224 unsigned Spaces = 8-(VCol & 7);
225
226 // Get the location of the tab.
227 SourceLocation TabLoc =
228 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
229
230 // Rewrite the single tab character into a sequence of spaces.
231 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
232 }
Chris Lattner8a12c272007-10-11 18:38:32 +0000233}
234
235
Chris Lattnerf04da132007-10-24 17:06:59 +0000236void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
237 int numDecls = ClassDecl->getNumForwardDecls();
238 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
239
240 // Get the start location and compute the semi location.
241 SourceLocation startLoc = ClassDecl->getLocation();
242 const char *startBuf = SM->getCharacterData(startLoc);
243 const char *semiPtr = strchr(startBuf, ';');
244
245 // Translate to typedef's that forward reference structs with the same name
246 // as the class. As a convenience, we include the original declaration
247 // as a comment.
248 std::string typedefString;
249 typedefString += "// ";
Steve Naroff934f2762007-10-24 22:48:43 +0000250 typedefString.append(startBuf, semiPtr-startBuf+1);
251 typedefString += "\n";
252 for (int i = 0; i < numDecls; i++) {
253 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
254 typedefString += "typedef struct ";
255 typedefString += ForwardDecl->getName();
256 typedefString += " ";
257 typedefString += ForwardDecl->getName();
258 typedefString += ";\n";
259 }
260
261 // Replace the @class with typedefs corresponding to the classes.
262 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
263 typedefString.c_str(), typedefString.size());
Chris Lattnerf04da132007-10-24 17:06:59 +0000264}
265
Steve Naroffbef11852007-10-26 20:53:56 +0000266void RewriteTest::RewriteInterfaceDecl(ObjcInterfaceDecl *ClassDecl) {
267 int nInstanceMethods = ClassDecl->getNumInstanceMethods();
268 ObjcMethodDecl **instanceMethods = ClassDecl->getInstanceMethods();
269
270 for (int i = 0; i < nInstanceMethods; i++) {
271 ObjcMethodDecl *instanceMethod = instanceMethods[i];
272 SourceLocation Loc = instanceMethod->getLocStart();
273
274 Rewrite.ReplaceText(Loc, 0, "// ", 3);
275
276 // FIXME: handle methods that are declared across multiple lines.
277 }
278 int nClassMethods = ClassDecl->getNumClassMethods();
279 ObjcMethodDecl **classMethods = ClassDecl->getClassMethods();
280
281 for (int i = 0; i < nClassMethods; i++) {
282 ObjcMethodDecl *classMethod = classMethods[i];
283 SourceLocation Loc = classMethod->getLocStart();
284
285 Rewrite.ReplaceText(Loc, 0, "// ", 3);
286
287 // FIXME: handle methods that are declared across multiple lines.
288 }
289}
290
Chris Lattnerf04da132007-10-24 17:06:59 +0000291//===----------------------------------------------------------------------===//
292// Function Body / Expression rewriting
293//===----------------------------------------------------------------------===//
294
Chris Lattnere64b7772007-10-24 16:57:36 +0000295Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner311ff022007-10-16 22:36:42 +0000296 // Otherwise, just rewrite all children.
297 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
298 CI != E; ++CI)
Chris Lattner50754772007-10-17 21:28:00 +0000299 if (*CI)
Chris Lattnere64b7772007-10-24 16:57:36 +0000300 *CI = RewriteFunctionBody(*CI);
Steve Naroffebf2b562007-10-23 23:50:29 +0000301
302 // Handle specific things.
303 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
304 return RewriteAtEncode(AtEncode);
305
Steve Naroff934f2762007-10-24 22:48:43 +0000306 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
307 // Before we rewrite it, put the original message expression in a comment.
308 SourceLocation startLoc = MessExpr->getLocStart();
309 SourceLocation endLoc = MessExpr->getLocEnd();
310
311 const char *startBuf = SM->getCharacterData(startLoc);
312 const char *endBuf = SM->getCharacterData(endLoc);
313
314 std::string messString;
315 messString += "// ";
316 messString.append(startBuf, endBuf-startBuf+1);
317 messString += "\n";
Steve Naroffbef11852007-10-26 20:53:56 +0000318
Steve Naroff934f2762007-10-24 22:48:43 +0000319 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
320 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
321 // Tried this, but it didn't work either...
Steve Naroffbef11852007-10-26 20:53:56 +0000322 Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffebf2b562007-10-23 23:50:29 +0000323 return RewriteMessageExpr(MessExpr);
Steve Naroff934f2762007-10-24 22:48:43 +0000324 }
Chris Lattnere64b7772007-10-24 16:57:36 +0000325 // Return this stmt unmodified.
326 return S;
Chris Lattner311ff022007-10-16 22:36:42 +0000327}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000328
Chris Lattnere64b7772007-10-24 16:57:36 +0000329Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattner01c57482007-10-17 22:35:30 +0000330 // Create a new string expression.
331 QualType StrType = Context->getPointerType(Context->CharTy);
Anders Carlsson85f9bce2007-10-29 05:01:08 +0000332 std::string StrEncoding;
333 Context->getObjcEncodingForType(Exp->getEncodedType(), StrEncoding);
334 Expr *Replacement = new StringLiteral(StrEncoding.c_str(),
335 StrEncoding.length(), false, StrType,
Chris Lattner01c57482007-10-17 22:35:30 +0000336 SourceLocation(), SourceLocation());
337 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattnere64b7772007-10-24 16:57:36 +0000338 delete Exp;
339 return Replacement;
Chris Lattner311ff022007-10-16 22:36:42 +0000340}
341
Steve Naroff934f2762007-10-24 22:48:43 +0000342CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
343 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffebf2b562007-10-23 23:50:29 +0000344 // Get the type, we will need to reference it in a couple spots.
Steve Naroff934f2762007-10-24 22:48:43 +0000345 QualType msgSendType = FD->getType();
Steve Naroffebf2b562007-10-23 23:50:29 +0000346
347 // Create a reference to the objc_msgSend() declaration.
Steve Naroff934f2762007-10-24 22:48:43 +0000348 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffebf2b562007-10-23 23:50:29 +0000349
350 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerf04da132007-10-24 17:06:59 +0000351 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffebf2b562007-10-23 23:50:29 +0000352 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
353
354 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattnere64b7772007-10-24 16:57:36 +0000355
Steve Naroff934f2762007-10-24 22:48:43 +0000356 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
357}
358
359Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
360 assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
361 assert(SelGetUidFunctionDecl && "Can't find sel_getUid() decl");
362 assert(GetClassFunctionDecl && "Can't find objc_getClass() decl");
363
364 // Synthesize a call to objc_msgSend().
365 llvm::SmallVector<Expr*, 8> MsgExprs;
366 IdentifierInfo *clsName = Exp->getClassName();
367
368 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
369 if (clsName) { // class message.
370 llvm::SmallVector<Expr*, 8> ClsExprs;
371 QualType argType = Context->getPointerType(Context->CharTy);
372 ClsExprs.push_back(new StringLiteral(clsName->getName(),
373 clsName->getLength(),
374 false, argType, SourceLocation(),
375 SourceLocation()));
376 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
377 &ClsExprs[0], ClsExprs.size());
378 MsgExprs.push_back(Cls);
379 } else // instance message.
380 MsgExprs.push_back(Exp->getReceiver());
381
382 // Create a call to sel_getUid("selName"), it will be the 2nd argument.
383 llvm::SmallVector<Expr*, 8> SelExprs;
384 QualType argType = Context->getPointerType(Context->CharTy);
385 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
386 Exp->getSelector().getName().size(),
387 false, argType, SourceLocation(),
388 SourceLocation()));
389 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
390 &SelExprs[0], SelExprs.size());
391 MsgExprs.push_back(SelExp);
392
393 // Now push any user supplied arguments.
394 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
395 MsgExprs.push_back(Exp->getArg(i));
396 // We've transferred the ownership to MsgExprs. Null out the argument in
397 // the original expression, since we will delete it below.
398 Exp->setArg(i, 0);
399 }
400 CallExpr *MessExp = SynthesizeCallToFunctionDecl(MsgSendFunctionDecl,
401 &MsgExprs[0], MsgExprs.size());
402 // Now do the actual rewrite.
403 Rewrite.ReplaceStmt(Exp, MessExp);
404
Chris Lattnere64b7772007-10-24 16:57:36 +0000405 delete Exp;
Steve Naroff934f2762007-10-24 22:48:43 +0000406 return MessExp;
Steve Naroffebf2b562007-10-23 23:50:29 +0000407}
408
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000409/// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
410/// an objective-c class with ivars.
411void RewriteTest::SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
412 std::string &Result) {
413 assert(CDecl && "Class missing in SynthesizeObjcInternalStruct");
414 assert(CDecl->getName() && "Name missing in SynthesizeObjcInternalStruct");
415 ObjcInterfaceDecl *RCDecl = CDecl->getSuperClass();
416 if (RCDecl && !ObjcSynthesizedStructs.count(RCDecl)) {
417 // Do it for the root
418 SynthesizeObjcInternalStruct(RCDecl, Result);
419 }
420
421 int NumIvars = CDecl->getIntfDeclNumIvars();
422 if (NumIvars <= 0 && (!RCDecl || !ObjcSynthesizedStructs.count(RCDecl)))
423 return;
424
425 Result += "\nstruct _interface_";
426 Result += CDecl->getName();
427 Result += " {\n";
428 if (RCDecl && ObjcSynthesizedStructs.count(RCDecl)) {
429 Result += "\tstruct _interface_";
430 Result += RCDecl->getName();
431 Result += " _";
432 Result += RCDecl->getName();
433 Result += ";\n";
434 }
435
436 ObjcIvarDecl **Ivars = CDecl->getIntfDeclIvars();
437 for (int i = 0; i < NumIvars; i++) {
438 Result += "\t";
439 std::string Name = Ivars[i]->getName();
440 Ivars[i]->getType().getAsStringInternal(Name);
441 Result += Name;
442 Result += ";\n";
443 }
444 Result += "};\n";
445 // Mark this struct as having been generated.
446 if (!ObjcSynthesizedStructs.insert(CDecl))
447 assert(true && "struct already synthesize- SynthesizeObjcInternalStruct");
448}
449
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000450// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
451/// class methods.
452void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
453 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000454 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000455 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +0000456 const char *ClassName,
457 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000458 static bool objc_impl_method = false;
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000459 if (NumMethods > 0 && !objc_impl_method) {
460 /* struct _objc_method {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000461 SEL _cmd;
462 char *method_types;
463 void *_imp;
464 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000465 */
Chris Lattner158ecb92007-10-25 17:07:24 +0000466 Result += "\nstruct _objc_method {\n";
467 Result += "\tSEL _cmd;\n";
468 Result += "\tchar *method_types;\n";
469 Result += "\tvoid *_imp;\n";
470 Result += "};\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000471
472 /* struct _objc_method_list {
473 struct _objc_method_list *next_method;
474 int method_count;
475 struct _objc_method method_list[];
476 }
477 */
478 Result += "\nstruct _objc_method_list {\n";
479 Result += "\tstruct _objc_method_list *next_method;\n";
480 Result += "\tint method_count;\n";
481 Result += "\tstruct _objc_method method_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000482 objc_impl_method = true;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000483 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000484 // Build _objc_method_list for class's methods if needed
485 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000486 Result += "\nstatic struct _objc_method_list _OBJC_";
Chris Lattner158ecb92007-10-25 17:07:24 +0000487 Result += prefix;
488 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
489 Result += "_METHODS_";
490 Result += ClassName;
491 Result += " __attribute__ ((section (\"__OBJC, __";
492 Result += IsInstanceMethod ? "inst" : "cls";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000493 Result += "_meth\")))= ";
494 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
495
496 Result += "\t,{{(SEL)\"";
497 Result += Methods[0]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000498 std::string MethodTypeString;
499 Context->getObjcEncodingForMethodDecl(Methods[0], MethodTypeString);
500 Result += "\", \"";
501 Result += MethodTypeString;
502 Result += "\", 0}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000503 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000504 // TODO: Need method address as 3rd initializer.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000505 Result += "\t ,{(SEL)\"";
506 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000507 std::string MethodTypeString;
508 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
509 Result += "\", \"";
510 Result += MethodTypeString;
511 Result += "\", 0}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000512 }
513 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000514 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000515}
516
517/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
518void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
519 int NumProtocols,
520 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000521 const char *ClassName,
522 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000523 static bool objc_protocol_methods = false;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000524 if (NumProtocols > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000525 for (int i = 0; i < NumProtocols; i++) {
526 ObjcProtocolDecl *PDecl = Protocols[i];
527 // Output struct protocol_methods holder of method selector and type.
528 if (!objc_protocol_methods &&
529 (PDecl->getNumInstanceMethods() > 0
530 || PDecl->getNumClassMethods() > 0)) {
531 /* struct protocol_methods {
532 SEL _cmd;
533 char *method_types;
534 }
535 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000536 Result += "\nstruct protocol_methods {\n";
537 Result += "\tSEL _cmd;\n";
538 Result += "\tchar *method_types;\n";
539 Result += "};\n";
540
541 /* struct _objc_protocol_method_list {
542 int protocol_method_count;
543 struct protocol_methods protocols[];
544 }
545 */
546 Result += "\nstruct _objc_protocol_method_list {\n";
547 Result += "\tint protocol_method_count;\n";
548 Result += "\tstruct protocol_methods protocols[];\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000549 objc_protocol_methods = true;
550 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000551
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000552 // Output instance methods declared in this protocol.
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000553 int NumMethods = PDecl->getNumInstanceMethods();
554 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000555 Result += "\nstatic struct _objc_protocol_method_list "
556 "_OBJC_PROTOCOL_INSTANCE_METHODS_";
557 Result += PDecl->getName();
558 Result += " __attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
559 "{\n\t" + utostr(NumMethods) + "\n";
560
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000561 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000562 Result += "\t,{{(SEL)\"";
563 Result += Methods[0]->getSelector().getName().c_str();
564 Result += "\", \"\"}\n";
565
566 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000567 Result += "\t ,{(SEL)\"";
568 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000569 std::string MethodTypeString;
570 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
571 Result += "\", \"";
572 Result += MethodTypeString;
573 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000574 }
575 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000576 }
577
578 // Output class methods declared in this protocol.
579 NumMethods = PDecl->getNumClassMethods();
580 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000581 Result += "\nstatic struct _objc_protocol_method_list "
582 "_OBJC_PROTOCOL_CLASS_METHODS_";
583 Result += PDecl->getName();
584 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
585 "{\n\t";
586 Result += utostr(NumMethods);
587 Result += "\n";
588
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000589 ObjcMethodDecl **Methods = PDecl->getClassMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000590 Result += "\t,{{(SEL)\"";
591 Result += Methods[0]->getSelector().getName().c_str();
592 Result += "\", \"\"}\n";
593
594 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000595 Result += "\t ,{(SEL)\"";
596 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000597 std::string MethodTypeString;
598 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
599 Result += "\", \"";
600 Result += MethodTypeString;
601 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000602 }
603 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000604 }
605 // Output:
606 /* struct _objc_protocol {
607 // Objective-C 1.0 extensions
608 struct _objc_protocol_extension *isa;
609 char *protocol_name;
610 struct _objc_protocol **protocol_list;
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000611 struct _objc_protocol_method_list *instance_methods;
612 struct _objc_protocol_method_list *class_methods;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000613 };
614 */
615 static bool objc_protocol = false;
616 if (!objc_protocol) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000617 Result += "\nstruct _objc_protocol {\n";
618 Result += "\tstruct _objc_protocol_extension *isa;\n";
619 Result += "\tchar *protocol_name;\n";
620 Result += "\tstruct _objc_protocol **protocol_list;\n";
621 Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
622 Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
623 Result += "};\n";
624
625 /* struct _objc_protocol_list {
626 struct _objc_protocol_list *next;
627 int protocol_count;
628 struct _objc_protocol *class_protocols[];
629 }
630 */
631 Result += "\nstruct _objc_protocol_list {\n";
632 Result += "\tstruct _objc_protocol_list *next;\n";
633 Result += "\tint protocol_count;\n";
634 Result += "\tstruct _objc_protocol *class_protocols[];\n";
635 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000636 objc_protocol = true;
637 }
638
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000639 Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
640 Result += PDecl->getName();
641 Result += " __attribute__ ((section (\"__OBJC, __protocol\")))= "
642 "{\n\t0, \"";
643 Result += PDecl->getName();
644 Result += "\", 0, ";
645 if (PDecl->getInstanceMethods() > 0) {
646 Result += "&_OBJC_PROTOCOL_INSTANCE_METHODS_";
647 Result += PDecl->getName();
648 Result += ", ";
649 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000650 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000651 Result += "0, ";
652 if (PDecl->getClassMethods() > 0) {
653 Result += "&_OBJC_PROTOCOL_CLASS_METHODS_";
654 Result += PDecl->getName();
655 Result += "\n";
656 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000657 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000658 Result += "0\n";
659 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000660 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000661 // Output the top lovel protocol meta-data for the class.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000662 Result += "\nstatic struct _objc_protocol_list _OBJC_";
663 Result += prefix;
664 Result += "_PROTOCOLS_";
665 Result += ClassName;
666 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
667 "{\n\t0, ";
668 Result += utostr(NumProtocols);
669 Result += "\n";
670
671 Result += "\t,{&_OBJC_PROTOCOL_";
672 Result += Protocols[0]->getName();
673 Result += " \n";
674
675 for (int i = 1; i < NumProtocols; i++) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000676 ObjcProtocolDecl *PDecl = Protocols[i];
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000677 Result += "\t ,&_OBJC_PROTOCOL_";
678 Result += PDecl->getName();
679 Result += "\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000680 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000681 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000682 }
683}
684
685/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
686/// implementation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000687void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl,
688 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000689 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
690 // Find category declaration for this implementation.
691 ObjcCategoryDecl *CDecl;
692 for (CDecl = ClassDecl->getCategoryList(); CDecl;
693 CDecl = CDecl->getNextClassCategory())
694 if (CDecl->getIdentifier() == IDecl->getIdentifier())
695 break;
696 assert(CDecl && "RewriteObjcCategoryImplDecl - bad category");
697
698 char *FullCategoryName = (char*)alloca(
699 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
700 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
701
702 // Build _objc_method_list for class's instance methods if needed
703 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
704 IDecl->getNumInstanceMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000705 true,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000706 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000707
708 // Build _objc_method_list for class's class methods if needed
709 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
710 IDecl->getNumClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000711 false,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000712 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000713
714 // Protocols referenced in class declaration?
715 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
716 CDecl->getNumReferencedProtocols(),
717 "CATEGORY",
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000718 FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000719
720 /* struct _objc_category {
721 char *category_name;
722 char *class_name;
723 struct _objc_method_list *instance_methods;
724 struct _objc_method_list *class_methods;
725 struct _objc_protocol_list *protocols;
726 // Objective-C 1.0 extensions
727 uint32_t size; // sizeof (struct _objc_category)
728 struct _objc_property_list *instance_properties; // category's own
729 // @property decl.
730 };
731 */
732
733 static bool objc_category = false;
734 if (!objc_category) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000735 Result += "\nstruct _objc_category {\n";
736 Result += "\tchar *category_name;\n";
737 Result += "\tchar *class_name;\n";
738 Result += "\tstruct _objc_method_list *instance_methods;\n";
739 Result += "\tstruct _objc_method_list *class_methods;\n";
740 Result += "\tstruct _objc_protocol_list *protocols;\n";
741 Result += "\tunsigned int size;\n";
742 Result += "\tstruct _objc_property_list *instance_properties;\n";
743 Result += "};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000744 objc_category = true;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000745 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000746 Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
747 Result += FullCategoryName;
748 Result += " __attribute__ ((section (\"__OBJC, __category\")))= {\n\t\"";
749 Result += IDecl->getName();
750 Result += "\"\n\t, \"";
751 Result += ClassDecl->getName();
752 Result += "\"\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000753
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000754 if (IDecl->getNumInstanceMethods() > 0) {
755 Result += "\t, (struct _objc_method_list *)"
756 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
757 Result += FullCategoryName;
758 Result += "\n";
759 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000760 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000761 Result += "\t, 0\n";
762 if (IDecl->getNumClassMethods() > 0) {
763 Result += "\t, (struct _objc_method_list *)"
764 "&_OBJC_CATEGORY_CLASS_METHODS_";
765 Result += FullCategoryName;
766 Result += "\n";
767 }
768 else
769 Result += "\t, 0\n";
770
771 if (CDecl->getNumReferencedProtocols() > 0) {
772 Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
773 Result += FullCategoryName;
774 Result += "\n";
775 }
776 else
777 Result += "\t, 0\n";
778 Result += "\t, sizeof(struct _objc_category), 0\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000779}
780
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000781/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
782/// ivar offset.
783void RewriteTest::SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
784 ObjcIvarDecl *ivar,
785 std::string &Result) {
786 Result += "offsetof(struct _interface_";
787 Result += IDecl->getName();
788 Result += ", ";
789 Result += ivar->getName();
790 Result += ")";
791}
792
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000793//===----------------------------------------------------------------------===//
794// Meta Data Emission
795//===----------------------------------------------------------------------===//
796
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000797void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
798 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000799 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
800
801 // Build _objc_ivar_list metadata for classes ivars if needed
802 int NumIvars = IDecl->getImplDeclNumIvars() > 0
803 ? IDecl->getImplDeclNumIvars()
804 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
805
Fariborz Jahanian4d733d32007-10-26 23:09:28 +0000806 SynthesizeObjcInternalStruct(CDecl, Result);
807
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000808 if (NumIvars > 0) {
809 static bool objc_ivar = false;
810 if (!objc_ivar) {
811 /* struct _objc_ivar {
812 char *ivar_name;
813 char *ivar_type;
814 int ivar_offset;
815 };
816 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000817 Result += "\nstruct _objc_ivar {\n";
818 Result += "\tchar *ivar_name;\n";
819 Result += "\tchar *ivar_type;\n";
820 Result += "\tint ivar_offset;\n";
821 Result += "};\n";
822
823 /* struct _objc_ivar_list {
824 int ivar_count;
825 struct _objc_ivar ivar_list[];
826 };
827 */
828 Result += "\nstruct _objc_ivar_list {\n";
829 Result += "\tint ivar_count;\n";
830 Result += "\tstruct _objc_ivar ivar_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000831 objc_ivar = true;
832 }
833
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000834 Result += "\nstatic struct _objc_ivar_list _OBJC_INSTANCE_VARIABLES_";
835 Result += IDecl->getName();
836 Result += " __attribute__ ((section (\"__OBJC, __instance_vars\")))= "
837 "{\n\t";
838 Result += utostr(NumIvars);
839 Result += "\n";
840
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000841 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
842 ? IDecl->getImplDeclIVars()
843 : CDecl->getIntfDeclIvars();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000844 Result += "\t,{{\"";
845 Result += Ivars[0]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +0000846 Result += "\", \"";
847 std::string StrEncoding;
848 Context->getObjcEncodingForType(Ivars[0]->getType(), StrEncoding);
849 Result += StrEncoding;
850 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000851 SynthesizeIvarOffsetComputation(IDecl, Ivars[0], Result);
852 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000853 for (int i = 1; i < NumIvars; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000854 Result += "\t ,{\"";
855 Result += Ivars[i]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +0000856 Result += "\", \"";
857 std::string StrEncoding;
858 Context->getObjcEncodingForType(Ivars[i]->getType(), StrEncoding);
859 Result += StrEncoding;
860 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000861 SynthesizeIvarOffsetComputation(IDecl, Ivars[i], Result);
862 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000863 }
864
865 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000866 }
867
868 // Build _objc_method_list for class's instance methods if needed
869 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
870 IDecl->getNumInstanceMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000871 true,
872 "", IDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000873
874 // Build _objc_method_list for class's class methods if needed
875 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000876 IDecl->getNumClassMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000877 false,
878 "", IDecl->getName(), Result);
879
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000880 // Protocols referenced in class declaration?
881 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
882 CDecl->getNumIntfRefProtocols(),
883 "CLASS",
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000884 CDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000885
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000886
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000887 // Declaration of class/meta-class metadata
888 /* struct _objc_class {
889 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000890 const char *super_class_name;
891 char *name;
892 long version;
893 long info;
894 long instance_size;
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000895 struct _objc_ivar_list *ivars;
896 struct _objc_method_list *methods;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000897 struct objc_cache *cache;
898 struct objc_protocol_list *protocols;
899 const char *ivar_layout;
900 struct _objc_class_ext *ext;
901 };
902 */
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000903 static bool objc_class = false;
904 if (!objc_class) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000905 Result += "\nstruct _objc_class {\n";
906 Result += "\tstruct _objc_class *isa;\n";
907 Result += "\tconst char *super_class_name;\n";
908 Result += "\tchar *name;\n";
909 Result += "\tlong version;\n";
910 Result += "\tlong info;\n";
911 Result += "\tlong instance_size;\n";
912 Result += "\tstruct _objc_ivar_list *ivars;\n";
913 Result += "\tstruct _objc_method_list *methods;\n";
914 Result += "\tstruct objc_cache *cache;\n";
915 Result += "\tstruct _objc_protocol_list *protocols;\n";
916 Result += "\tconst char *ivar_layout;\n";
917 Result += "\tstruct _objc_class_ext *ext;\n";
918 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000919 objc_class = true;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000920 }
921
922 // Meta-class metadata generation.
923 ObjcInterfaceDecl *RootClass = 0;
924 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
925 while (SuperClass) {
926 RootClass = SuperClass;
927 SuperClass = SuperClass->getSuperClass();
928 }
929 SuperClass = CDecl->getSuperClass();
930
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000931 Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
932 Result += CDecl->getName();
933 Result += " __attribute__ ((section (\"__OBJC, __meta_class\")))= "
934 "{\n\t(struct _objc_class *)\"";
935 Result += (RootClass ? RootClass->getName() : CDecl->getName());
936 Result += "\"";
937
938 if (SuperClass) {
939 Result += ", \"";
940 Result += SuperClass->getName();
941 Result += "\", \"";
942 Result += CDecl->getName();
943 Result += "\"";
944 }
945 else {
946 Result += ", 0, \"";
947 Result += CDecl->getName();
948 Result += "\"";
949 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000950 // TODO: 'ivars' field for root class is currently set to 0.
951 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000952 Result += ", 0,2, sizeof(struct _objc_class), 0";
953 if (CDecl->getNumClassMethods() > 0) {
954 Result += "\n\t, &_OBJC_CLASS_METHODS_";
955 Result += CDecl->getName();
956 Result += "\n";
957 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000958 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000959 Result += ", 0\n";
960 if (CDecl->getNumIntfRefProtocols() > 0) {
961 Result += "\t,0, &_OBJC_CLASS_PROTOCOLS_";
962 Result += CDecl->getName();
963 Result += ",0,0\n";
964 }
Fariborz Jahanian454cb012007-10-24 20:54:23 +0000965 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000966 Result += "\t,0,0,0,0\n";
967 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000968
969 // class metadata generation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000970 Result += "\nstatic struct _objc_class _OBJC_CLASS_";
971 Result += CDecl->getName();
972 Result += " __attribute__ ((section (\"__OBJC, __class\")))= "
973 "{\n\t&_OBJC_METACLASS_";
974 Result += CDecl->getName();
975 if (SuperClass) {
976 Result += ", \"";
977 Result += SuperClass->getName();
978 Result += "\", \"";
979 Result += CDecl->getName();
980 Result += "\"";
981 }
982 else {
983 Result += ", 0, \"";
984 Result += CDecl->getName();
985 Result += "\"";
986 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000987 // 'info' field is initialized to CLS_CLASS(1) for class
Fariborz Jahanian4d733d32007-10-26 23:09:28 +0000988 Result += ", 0,1";
989 if (!ObjcSynthesizedStructs.count(CDecl))
990 Result += ",0";
991 else {
992 // class has size. Must synthesize its size.
993 Result += ",sizeof(struct _interface_";
994 Result += CDecl->getName();
995 Result += ")";
996 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000997 if (NumIvars > 0) {
998 Result += ", &_OBJC_INSTANCE_VARIABLES_";
999 Result += CDecl->getName();
1000 Result += "\n\t";
1001 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001002 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001003 Result += ",0";
1004 if (IDecl->getNumInstanceMethods() > 0) {
1005 Result += ", &_OBJC_INSTANCE_METHODS_";
1006 Result += CDecl->getName();
1007 Result += ", 0\n\t";
1008 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001009 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001010 Result += ",0,0";
1011 if (CDecl->getNumIntfRefProtocols() > 0) {
1012 Result += ", &_OBJC_CLASS_PROTOCOLS_";
1013 Result += CDecl->getName();
1014 Result += ", 0,0\n";
1015 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001016 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001017 Result += ",0,0,0\n";
1018 Result += "};\n";
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001019}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001020
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001021void RewriteTest::WriteObjcMetaData(std::string &Result) {
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001022 int ClsDefCount = ClassImplementation.size();
1023 int CatDefCount = CategoryImplementation.size();
1024 if (ClsDefCount == 0 && CatDefCount == 0)
1025 return;
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001026
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001027 // TODO: This is temporary until we decide how to access objc types in a
1028 // c program
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001029 Result += "#include <Objc/objc.h>\n";
1030 // This is needed for use of offsetof
1031 Result += "#include <stddef.h>\n";
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001032
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001033 // For each implemented class, write out all its meta data.
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001034 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001035 RewriteObjcClassMetaData(ClassImplementation[i], Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001036
1037 // For each implemented category, write out all its meta data.
1038 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001039 RewriteObjcCategoryImplDecl(CategoryImplementation[i], Result);
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001040
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001041 // Write objc_symtab metadata
1042 /*
1043 struct _objc_symtab
1044 {
1045 long sel_ref_cnt;
1046 SEL *refs;
1047 short cls_def_cnt;
1048 short cat_def_cnt;
1049 void *defs[cls_def_cnt + cat_def_cnt];
1050 };
1051 */
1052
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001053 Result += "\nstruct _objc_symtab {\n";
1054 Result += "\tlong sel_ref_cnt;\n";
1055 Result += "\tSEL *refs;\n";
1056 Result += "\tshort cls_def_cnt;\n";
1057 Result += "\tshort cat_def_cnt;\n";
1058 Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
1059 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001060
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001061 Result += "static struct _objc_symtab "
1062 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n";
1063 Result += "\t0, 0, " + utostr(ClsDefCount)
1064 + ", " + utostr(CatDefCount) + "\n";
1065 for (int i = 0; i < ClsDefCount; i++) {
1066 Result += "\t,&_OBJC_CLASS_";
1067 Result += ClassImplementation[i]->getName();
1068 Result += "\n";
1069 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001070
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001071 for (int i = 0; i < CatDefCount; i++) {
1072 Result += "\t,&_OBJC_CATEGORY_";
1073 Result += CategoryImplementation[i]->getClassInterface()->getName();
1074 Result += "_";
1075 Result += CategoryImplementation[i]->getName();
1076 Result += "\n";
1077 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001078
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001079 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001080
1081 // Write objc_module metadata
1082
1083 /*
1084 struct _objc_module {
1085 long version;
1086 long size;
1087 const char *name;
1088 struct _objc_symtab *symtab;
1089 }
1090 */
1091
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001092 Result += "\nstruct _objc_module {\n";
1093 Result += "\tlong version;\n";
1094 Result += "\tlong size;\n";
1095 Result += "\tconst char *name;\n";
1096 Result += "\tstruct _objc_symtab *symtab;\n";
1097 Result += "};\n\n";
1098 Result += "static struct _objc_module "
1099 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001100 Result += "\t" + utostr(OBJC_ABI_VERSION) +
1101 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001102 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001103}
Chris Lattner311ff022007-10-16 22:36:42 +00001104