blob: e2516c850e9ba6d45773a33919f055454dedcbfa [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"
Steve Naroff2feac5e2007-10-30 03:43:13 +000022#include "clang/Lex/Lexer.h"
Chris Lattner77cd2a02007-10-11 00:43:27 +000023using namespace clang;
Chris Lattner158ecb92007-10-25 17:07:24 +000024using llvm::utostr;
Chris Lattner77cd2a02007-10-11 00:43:27 +000025
Chris Lattner77cd2a02007-10-11 00:43:27 +000026namespace {
Chris Lattner8a12c272007-10-11 18:38:32 +000027 class RewriteTest : public ASTConsumer {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000028 Rewriter Rewrite;
Chris Lattner01c57482007-10-17 22:35:30 +000029 ASTContext *Context;
Chris Lattner77cd2a02007-10-11 00:43:27 +000030 SourceManager *SM;
Chris Lattner8a12c272007-10-11 18:38:32 +000031 unsigned MainFileID;
Chris Lattner2c64b7b2007-10-16 21:07:07 +000032 SourceLocation LastIncLoc;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000033 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
34 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000035 llvm::SmallPtrSet<ObjcInterfaceDecl*, 8> ObjcSynthesizedStructs;
Steve Naroff8749be52007-10-31 22:11:35 +000036 llvm::SmallPtrSet<ObjcInterfaceDecl*, 8> ObjcForwardDecls;
Steve Naroffebf2b562007-10-23 23:50:29 +000037
38 FunctionDecl *MsgSendFunctionDecl;
39 FunctionDecl *GetClassFunctionDecl;
Steve Naroff934f2762007-10-24 22:48:43 +000040 FunctionDecl *SelGetUidFunctionDecl;
Steve Naroffebf2b562007-10-23 23:50:29 +000041
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000042 static const int OBJC_ABI_VERSION =7 ;
Chris Lattner77cd2a02007-10-11 00:43:27 +000043 public:
Chris Lattner01c57482007-10-17 22:35:30 +000044 void Initialize(ASTContext &context, unsigned mainFileID) {
45 Context = &context;
46 SM = &Context->SourceMgr;
Chris Lattner8a12c272007-10-11 18:38:32 +000047 MainFileID = mainFileID;
Steve Naroffebf2b562007-10-23 23:50:29 +000048 MsgSendFunctionDecl = 0;
Steve Naroffc0006092007-10-24 01:09:48 +000049 GetClassFunctionDecl = 0;
Steve Naroff934f2762007-10-24 22:48:43 +000050 SelGetUidFunctionDecl = 0;
Chris Lattner01c57482007-10-17 22:35:30 +000051 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattner77cd2a02007-10-11 00:43:27 +000052 }
Chris Lattner8a12c272007-10-11 18:38:32 +000053
Chris Lattnerf04da132007-10-24 17:06:59 +000054 // Top Level Driver code.
55 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner2c64b7b2007-10-16 21:07:07 +000056 void HandleDeclInMainFile(Decl *D);
Chris Lattnerf04da132007-10-24 17:06:59 +000057 ~RewriteTest();
58
59 // Syntactic Rewriting.
Chris Lattner2c64b7b2007-10-16 21:07:07 +000060 void RewriteInclude(SourceLocation Loc);
Chris Lattnerf04da132007-10-24 17:06:59 +000061 void RewriteTabs();
62 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Steve Naroffbef11852007-10-26 20:53:56 +000063 void RewriteInterfaceDecl(ObjcInterfaceDecl *Dcl);
Steve Naroff423cb562007-10-30 13:30:57 +000064 void RewriteCategoryDecl(ObjcCategoryDecl *Dcl);
Steve Naroff752d6ef2007-10-30 16:42:30 +000065 void RewriteProtocolDecl(ObjcProtocolDecl *Dcl);
Steve Naroff423cb562007-10-30 13:30:57 +000066 void RewriteMethods(int nMethods, ObjcMethodDecl **Methods);
Steve Naroff09b266e2007-10-30 23:14:51 +000067 void RewriteFunctionDecl(FunctionDecl *FD);
Steve Naroffd5255f52007-11-01 13:24:47 +000068 void RewriteObjcQualifiedInterfaceTypes(
69 const FunctionTypeProto *proto, FunctionDecl *FD);
70 bool needToScanForQualifiers(QualType T);
Chris Lattner311ff022007-10-16 22:36:42 +000071
Chris Lattnerf04da132007-10-24 17:06:59 +000072 // Expression Rewriting.
Chris Lattnere64b7772007-10-24 16:57:36 +000073 Stmt *RewriteFunctionBody(Stmt *S);
74 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
75 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroff934f2762007-10-24 22:48:43 +000076 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
77 Expr **args, unsigned nargs);
Steve Naroff09b266e2007-10-30 23:14:51 +000078 void SynthMsgSendFunctionDecl();
79 void SynthGetClassFunctionDecl();
80
Chris Lattnerf04da132007-10-24 17:06:59 +000081 // Metadata emission.
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000082 void HandleObjcMetaDataEmission();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000083 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
84 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000085
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000086 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl,
87 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000088
89 void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
90 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +000091 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000092 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +000093 const char *ClassName,
94 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000095
96 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
97 int NumProtocols,
98 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000099 const char *ClassName,
100 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000101 void SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
102 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000103 void SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
104 ObjcIvarDecl *ivar,
105 std::string &Result);
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000106 void WriteObjcMetaData(std::string &Result);
Chris Lattner77cd2a02007-10-11 00:43:27 +0000107 };
108}
109
Chris Lattner8a12c272007-10-11 18:38:32 +0000110ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattner77cd2a02007-10-11 00:43:27 +0000111
Chris Lattnerf04da132007-10-24 17:06:59 +0000112//===----------------------------------------------------------------------===//
113// Top Level Driver Code
114//===----------------------------------------------------------------------===//
115
Chris Lattner8a12c272007-10-11 18:38:32 +0000116void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000117 // Two cases: either the decl could be in the main file, or it could be in a
118 // #included file. If the former, rewrite it now. If the later, check to see
119 // if we rewrote the #include/#import.
120 SourceLocation Loc = D->getLocation();
121 Loc = SM->getLogicalLoc(Loc);
122
123 // If this is for a builtin, ignore it.
124 if (Loc.isInvalid()) return;
125
Steve Naroffebf2b562007-10-23 23:50:29 +0000126 // Look for built-in declarations that we need to refer during the rewrite.
127 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroff09b266e2007-10-30 23:14:51 +0000128 RewriteFunctionDecl(FD);
Steve Naroffbef11852007-10-26 20:53:56 +0000129 } else if (ObjcInterfaceDecl *MD = dyn_cast<ObjcInterfaceDecl>(D)) {
130 RewriteInterfaceDecl(MD);
Steve Naroff423cb562007-10-30 13:30:57 +0000131 } else if (ObjcCategoryDecl *CD = dyn_cast<ObjcCategoryDecl>(D)) {
132 RewriteCategoryDecl(CD);
Steve Naroff752d6ef2007-10-30 16:42:30 +0000133 } else if (ObjcProtocolDecl *PD = dyn_cast<ObjcProtocolDecl>(D)) {
134 RewriteProtocolDecl(PD);
Steve Naroffebf2b562007-10-23 23:50:29 +0000135 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000136 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000137 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
138 return HandleDeclInMainFile(D);
139
Chris Lattnerf04da132007-10-24 17:06:59 +0000140 // Otherwise, see if there is a #import in the main file that should be
141 // rewritten.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000142 RewriteInclude(Loc);
143}
144
Chris Lattnerf04da132007-10-24 17:06:59 +0000145/// HandleDeclInMainFile - This is called for each top-level decl defined in the
146/// main file of the input.
147void RewriteTest::HandleDeclInMainFile(Decl *D) {
148 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
149 if (Stmt *Body = FD->getBody())
150 FD->setBody(RewriteFunctionBody(Body));
151
152 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
153 ClassImplementation.push_back(CI);
154 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
155 CategoryImplementation.push_back(CI);
156 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
157 RewriteForwardClassDecl(CD);
158 // Nothing yet.
159}
160
161RewriteTest::~RewriteTest() {
162 // Get the top-level buffer that this corresponds to.
163 RewriteTabs();
164
165 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
166 // we are done.
167 if (const RewriteBuffer *RewriteBuf =
168 Rewrite.getRewriteBufferFor(MainFileID)) {
169 printf("Changed:\n");
170 std::string S(RewriteBuf->begin(), RewriteBuf->end());
171 printf("%s\n", S.c_str());
172 } else {
173 printf("No changes\n");
174 }
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000175
176}
177
178/// HandleObjcMetaDataEmission - main routine to generate objective-c's
179/// metadata.
180void RewriteTest::HandleObjcMetaDataEmission() {
Chris Lattnerf04da132007-10-24 17:06:59 +0000181 // Rewrite Objective-c meta data*
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000182 std::string ResultStr;
183 WriteObjcMetaData(ResultStr);
184 // For now just print the string out.
185 printf("%s", ResultStr.c_str());
Chris Lattnerf04da132007-10-24 17:06:59 +0000186}
187
188//===----------------------------------------------------------------------===//
189// Syntactic (non-AST) Rewriting Code
190//===----------------------------------------------------------------------===//
191
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000192void RewriteTest::RewriteInclude(SourceLocation Loc) {
193 // Rip up the #include stack to the main file.
194 SourceLocation IncLoc = Loc, NextLoc = Loc;
195 do {
196 IncLoc = Loc;
197 Loc = SM->getLogicalLoc(NextLoc);
198 NextLoc = SM->getIncludeLoc(Loc);
199 } while (!NextLoc.isInvalid());
200
201 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
202 // IncLoc indicates the header that was included if it is useful.
203 IncLoc = SM->getLogicalLoc(IncLoc);
204 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
205 Loc == LastIncLoc)
206 return;
207 LastIncLoc = Loc;
208
209 unsigned IncCol = SM->getColumnNumber(Loc);
210 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
211
212 // Replace the #import with #include.
213 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
214}
215
Chris Lattnerf04da132007-10-24 17:06:59 +0000216void RewriteTest::RewriteTabs() {
217 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
218 const char *MainBufStart = MainBuf.first;
219 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000220
Chris Lattnerf04da132007-10-24 17:06:59 +0000221 // Loop over the whole file, looking for tabs.
222 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
223 if (*BufPtr != '\t')
224 continue;
225
226 // Okay, we found a tab. This tab will turn into at least one character,
227 // but it depends on which 'virtual column' it is in. Compute that now.
228 unsigned VCol = 0;
229 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
230 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
231 ++VCol;
232
233 // Okay, now that we know the virtual column, we know how many spaces to
234 // insert. We assume 8-character tab-stops.
235 unsigned Spaces = 8-(VCol & 7);
236
237 // Get the location of the tab.
238 SourceLocation TabLoc =
239 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
240
241 // Rewrite the single tab character into a sequence of spaces.
242 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
243 }
Chris Lattner8a12c272007-10-11 18:38:32 +0000244}
245
246
Chris Lattnerf04da132007-10-24 17:06:59 +0000247void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
248 int numDecls = ClassDecl->getNumForwardDecls();
249 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
250
251 // Get the start location and compute the semi location.
252 SourceLocation startLoc = ClassDecl->getLocation();
253 const char *startBuf = SM->getCharacterData(startLoc);
254 const char *semiPtr = strchr(startBuf, ';');
255
256 // Translate to typedef's that forward reference structs with the same name
257 // as the class. As a convenience, we include the original declaration
258 // as a comment.
259 std::string typedefString;
260 typedefString += "// ";
Steve Naroff934f2762007-10-24 22:48:43 +0000261 typedefString.append(startBuf, semiPtr-startBuf+1);
262 typedefString += "\n";
263 for (int i = 0; i < numDecls; i++) {
264 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
Steve Naroff8749be52007-10-31 22:11:35 +0000265 if (ObjcForwardDecls.count(ForwardDecl))
266 continue;
Steve Naroff934f2762007-10-24 22:48:43 +0000267 typedefString += "typedef struct ";
268 typedefString += ForwardDecl->getName();
269 typedefString += " ";
270 typedefString += ForwardDecl->getName();
271 typedefString += ";\n";
Steve Naroff8749be52007-10-31 22:11:35 +0000272
273 // Mark this typedef as having been generated.
274 if (!ObjcForwardDecls.insert(ForwardDecl))
Fariborz Jahanianaff56d02007-10-31 22:57:04 +0000275 assert(false && "typedef already output");
Steve Naroff934f2762007-10-24 22:48:43 +0000276 }
277
278 // Replace the @class with typedefs corresponding to the classes.
279 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
280 typedefString.c_str(), typedefString.size());
Chris Lattnerf04da132007-10-24 17:06:59 +0000281}
282
Steve Naroff423cb562007-10-30 13:30:57 +0000283void RewriteTest::RewriteMethods(int nMethods, ObjcMethodDecl **Methods) {
284 for (int i = 0; i < nMethods; i++) {
285 ObjcMethodDecl *Method = Methods[i];
286 SourceLocation Loc = Method->getLocStart();
287
288 Rewrite.ReplaceText(Loc, 0, "// ", 3);
289
290 // FIXME: handle methods that are declared across multiple lines.
291 }
292}
293
294void RewriteTest::RewriteCategoryDecl(ObjcCategoryDecl *CatDecl) {
295 SourceLocation LocStart = CatDecl->getLocStart();
296
297 // FIXME: handle category headers that are declared across multiple lines.
298 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
299
300 RewriteMethods(CatDecl->getNumInstanceMethods(),
301 CatDecl->getInstanceMethods());
302 RewriteMethods(CatDecl->getNumClassMethods(),
303 CatDecl->getClassMethods());
304 // Lastly, comment out the @end.
305 Rewrite.ReplaceText(CatDecl->getAtEndLoc(), 0, "// ", 3);
306}
307
Steve Naroff752d6ef2007-10-30 16:42:30 +0000308void RewriteTest::RewriteProtocolDecl(ObjcProtocolDecl *PDecl) {
309 SourceLocation LocStart = PDecl->getLocStart();
310
311 // FIXME: handle protocol headers that are declared across multiple lines.
312 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
313
314 RewriteMethods(PDecl->getNumInstanceMethods(),
315 PDecl->getInstanceMethods());
316 RewriteMethods(PDecl->getNumClassMethods(),
317 PDecl->getClassMethods());
318 // Lastly, comment out the @end.
319 Rewrite.ReplaceText(PDecl->getAtEndLoc(), 0, "// ", 3);
320}
321
Steve Naroffbef11852007-10-26 20:53:56 +0000322void RewriteTest::RewriteInterfaceDecl(ObjcInterfaceDecl *ClassDecl) {
Steve Narofff908a872007-10-30 02:23:23 +0000323
324 SourceLocation LocStart = ClassDecl->getLocStart();
325 SourceLocation LocEnd = ClassDecl->getLocEnd();
326
327 const char *startBuf = SM->getCharacterData(LocStart);
328 const char *endBuf = SM->getCharacterData(LocEnd);
329
Steve Naroff2feac5e2007-10-30 03:43:13 +0000330 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM);
Steve Narofff908a872007-10-30 02:23:23 +0000331
332 std::string ResultStr;
Steve Naroff6c6a2db2007-11-01 03:35:41 +0000333 if (!ObjcForwardDecls.count(ClassDecl)) {
334 // we haven't seen a forward decl - generate a typedef.
335 ResultStr += "typedef struct ";
336 ResultStr += ClassDecl->getName();
337 ResultStr += " ";
338 ResultStr += ClassDecl->getName();
339 ResultStr += ";";
340
341 // Mark this typedef as having been generated.
342 ObjcForwardDecls.insert(ClassDecl);
343 }
Steve Narofff908a872007-10-30 02:23:23 +0000344 SynthesizeObjcInternalStruct(ClassDecl, ResultStr);
345
Steve Naroff2feac5e2007-10-30 03:43:13 +0000346 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
Steve Narofff908a872007-10-30 02:23:23 +0000347 ResultStr.c_str(), ResultStr.size());
348
Steve Naroff423cb562007-10-30 13:30:57 +0000349 RewriteMethods(ClassDecl->getNumInstanceMethods(),
350 ClassDecl->getInstanceMethods());
351 RewriteMethods(ClassDecl->getNumClassMethods(),
352 ClassDecl->getClassMethods());
Steve Naroffbef11852007-10-26 20:53:56 +0000353
Steve Naroff2feac5e2007-10-30 03:43:13 +0000354 // Lastly, comment out the @end.
355 Rewrite.ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3);
Steve Naroffbef11852007-10-26 20:53:56 +0000356}
357
Chris Lattnerf04da132007-10-24 17:06:59 +0000358//===----------------------------------------------------------------------===//
359// Function Body / Expression rewriting
360//===----------------------------------------------------------------------===//
361
Chris Lattnere64b7772007-10-24 16:57:36 +0000362Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner311ff022007-10-16 22:36:42 +0000363 // Otherwise, just rewrite all children.
364 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
365 CI != E; ++CI)
Chris Lattner50754772007-10-17 21:28:00 +0000366 if (*CI)
Chris Lattnere64b7772007-10-24 16:57:36 +0000367 *CI = RewriteFunctionBody(*CI);
Steve Naroffebf2b562007-10-23 23:50:29 +0000368
369 // Handle specific things.
370 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
371 return RewriteAtEncode(AtEncode);
372
Steve Naroff934f2762007-10-24 22:48:43 +0000373 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
374 // Before we rewrite it, put the original message expression in a comment.
375 SourceLocation startLoc = MessExpr->getLocStart();
376 SourceLocation endLoc = MessExpr->getLocEnd();
377
378 const char *startBuf = SM->getCharacterData(startLoc);
379 const char *endBuf = SM->getCharacterData(endLoc);
380
381 std::string messString;
382 messString += "// ";
383 messString.append(startBuf, endBuf-startBuf+1);
384 messString += "\n";
Steve Naroffbef11852007-10-26 20:53:56 +0000385
Steve Naroff934f2762007-10-24 22:48:43 +0000386 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
387 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
388 // Tried this, but it didn't work either...
Steve Naroff752d6ef2007-10-30 16:42:30 +0000389 // Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffebf2b562007-10-23 23:50:29 +0000390 return RewriteMessageExpr(MessExpr);
Steve Naroff934f2762007-10-24 22:48:43 +0000391 }
Chris Lattnere64b7772007-10-24 16:57:36 +0000392 // Return this stmt unmodified.
393 return S;
Chris Lattner311ff022007-10-16 22:36:42 +0000394}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000395
Chris Lattnere64b7772007-10-24 16:57:36 +0000396Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattner01c57482007-10-17 22:35:30 +0000397 // Create a new string expression.
398 QualType StrType = Context->getPointerType(Context->CharTy);
Anders Carlsson85f9bce2007-10-29 05:01:08 +0000399 std::string StrEncoding;
400 Context->getObjcEncodingForType(Exp->getEncodedType(), StrEncoding);
401 Expr *Replacement = new StringLiteral(StrEncoding.c_str(),
402 StrEncoding.length(), false, StrType,
Chris Lattner01c57482007-10-17 22:35:30 +0000403 SourceLocation(), SourceLocation());
404 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattnere64b7772007-10-24 16:57:36 +0000405 delete Exp;
406 return Replacement;
Chris Lattner311ff022007-10-16 22:36:42 +0000407}
408
Steve Naroff934f2762007-10-24 22:48:43 +0000409CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
410 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffebf2b562007-10-23 23:50:29 +0000411 // Get the type, we will need to reference it in a couple spots.
Steve Naroff934f2762007-10-24 22:48:43 +0000412 QualType msgSendType = FD->getType();
Steve Naroffebf2b562007-10-23 23:50:29 +0000413
414 // Create a reference to the objc_msgSend() declaration.
Steve Naroff934f2762007-10-24 22:48:43 +0000415 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffebf2b562007-10-23 23:50:29 +0000416
417 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerf04da132007-10-24 17:06:59 +0000418 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffebf2b562007-10-23 23:50:29 +0000419 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
420
421 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattnere64b7772007-10-24 16:57:36 +0000422
Steve Naroff934f2762007-10-24 22:48:43 +0000423 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
424}
425
Steve Naroffd5255f52007-11-01 13:24:47 +0000426static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
427 const char *&startRef, const char *&endRef) {
428 while (startBuf < endBuf) {
429 if (*startBuf == '<')
430 startRef = startBuf; // mark the start.
431 if (*startBuf == '>') {
432 assert((startRef && *startRef == '<') && "rewrite scanning error");
433 endRef = startBuf; // mark the end.
434 return true;
435 }
436 startBuf++;
437 }
438 return false;
439}
440
441bool RewriteTest::needToScanForQualifiers(QualType T) {
442 // FIXME: we don't currently represent "id <Protocol>" in the type system.
443 if (T == Context->getObjcIdType())
444 return true;
445
446 if (const PointerType *pType = T->getAsPointerType()) {
Steve Naroff9165ad32007-10-31 04:38:33 +0000447 Type *pointeeType = pType->getPointeeType().getTypePtr();
448 if (isa<ObjcQualifiedInterfaceType>(pointeeType))
449 return true; // we have "Class <Protocol> *".
450 }
Steve Naroffd5255f52007-11-01 13:24:47 +0000451 return false;
452}
453
454void RewriteTest::RewriteObjcQualifiedInterfaceTypes(
455 const FunctionTypeProto *proto, FunctionDecl *FD) {
456
457 if (needToScanForQualifiers(proto->getResultType())) {
458 // Since types are unique, we need to scan the buffer.
459 SourceLocation Loc = FD->getLocation();
460
461 const char *endBuf = SM->getCharacterData(Loc);
462 const char *startBuf = endBuf;
463 while (*startBuf != ';')
464 startBuf--; // scan backward (from the decl location) for return type.
465 const char *startRef = 0, *endRef = 0;
466 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
467 // Get the locations of the startRef, endRef.
468 SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf);
469 SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1);
470 // Comment out the protocol references.
471 Rewrite.ReplaceText(LessLoc, 0, "/*", 2);
472 Rewrite.ReplaceText(GreaterLoc, 0, "*/", 2);
Steve Naroff9165ad32007-10-31 04:38:33 +0000473 }
474 }
Steve Naroffd5255f52007-11-01 13:24:47 +0000475 // Now check arguments.
476 for (unsigned i = 0; i < proto->getNumArgs(); i++) {
477 if (needToScanForQualifiers(proto->getArgType(i))) {
478 // Since types are unique, we need to scan the buffer.
479 SourceLocation Loc = FD->getLocation();
480
481 const char *startBuf = SM->getCharacterData(Loc);
482 const char *endBuf = startBuf;
483 while (*endBuf != ';')
484 endBuf++; // scan forward (from the decl location) for argument types.
485 const char *startRef = 0, *endRef = 0;
486 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
487 // Get the locations of the startRef, endRef.
488 SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf);
489 SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1);
490 // Comment out the protocol references.
491 Rewrite.ReplaceText(LessLoc, 0, "/*", 2);
492 Rewrite.ReplaceText(GreaterLoc, 0, "*/", 2);
493 }
494 }
495 }
Steve Naroff9165ad32007-10-31 04:38:33 +0000496}
497
Steve Naroff09b266e2007-10-30 23:14:51 +0000498void RewriteTest::RewriteFunctionDecl(FunctionDecl *FD) {
499 // declared in <objc/objc.h>
Steve Naroff9165ad32007-10-31 04:38:33 +0000500 if (strcmp(FD->getName(), "sel_getUid") == 0) {
Steve Naroff09b266e2007-10-30 23:14:51 +0000501 SelGetUidFunctionDecl = FD;
Steve Naroff9165ad32007-10-31 04:38:33 +0000502 return;
503 }
504 // Check for ObjC 'id' and class types that have been adorned with protocol
505 // information (id<p>, C<p>*). The protocol references need to be rewritten!
506 const FunctionType *funcType = FD->getType()->getAsFunctionType();
507 assert(funcType && "missing function type");
Steve Naroffd5255f52007-11-01 13:24:47 +0000508 if (const FunctionTypeProto *proto = dyn_cast<FunctionTypeProto>(funcType))
509 RewriteObjcQualifiedInterfaceTypes(proto, FD);
Steve Naroff09b266e2007-10-30 23:14:51 +0000510}
511
512// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
513void RewriteTest::SynthMsgSendFunctionDecl() {
514 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
515 llvm::SmallVector<QualType, 16> ArgTys;
516 QualType argT = Context->getObjcIdType();
517 assert(!argT.isNull() && "Can't find 'id' type");
518 ArgTys.push_back(argT);
519 argT = Context->getObjcSelType();
520 assert(!argT.isNull() && "Can't find 'SEL' type");
521 ArgTys.push_back(argT);
522 QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
523 &ArgTys[0], ArgTys.size(),
524 true /*isVariadic*/);
525 MsgSendFunctionDecl = new FunctionDecl(SourceLocation(),
526 msgSendIdent, msgSendType,
527 FunctionDecl::Extern, false, 0);
528}
529
530// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
531void RewriteTest::SynthGetClassFunctionDecl() {
532 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
533 llvm::SmallVector<QualType, 16> ArgTys;
534 ArgTys.push_back(Context->getPointerType(
535 Context->CharTy.getQualifiedType(QualType::Const)));
536 QualType getClassType = Context->getFunctionType(Context->getObjcIdType(),
537 &ArgTys[0], ArgTys.size(),
538 false /*isVariadic*/);
539 GetClassFunctionDecl = new FunctionDecl(SourceLocation(),
540 getClassIdent, getClassType,
541 FunctionDecl::Extern, false, 0);
542}
543
Steve Naroff934f2762007-10-24 22:48:43 +0000544Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
Steve Naroff934f2762007-10-24 22:48:43 +0000545 assert(SelGetUidFunctionDecl && "Can't find sel_getUid() decl");
Steve Naroff09b266e2007-10-30 23:14:51 +0000546 if (!MsgSendFunctionDecl)
547 SynthMsgSendFunctionDecl();
548 if (!GetClassFunctionDecl)
549 SynthGetClassFunctionDecl();
Steve Naroff934f2762007-10-24 22:48:43 +0000550
551 // Synthesize a call to objc_msgSend().
552 llvm::SmallVector<Expr*, 8> MsgExprs;
553 IdentifierInfo *clsName = Exp->getClassName();
554
555 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
556 if (clsName) { // class message.
557 llvm::SmallVector<Expr*, 8> ClsExprs;
558 QualType argType = Context->getPointerType(Context->CharTy);
559 ClsExprs.push_back(new StringLiteral(clsName->getName(),
560 clsName->getLength(),
561 false, argType, SourceLocation(),
562 SourceLocation()));
563 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
564 &ClsExprs[0], ClsExprs.size());
565 MsgExprs.push_back(Cls);
566 } else // instance message.
567 MsgExprs.push_back(Exp->getReceiver());
568
569 // Create a call to sel_getUid("selName"), it will be the 2nd argument.
570 llvm::SmallVector<Expr*, 8> SelExprs;
571 QualType argType = Context->getPointerType(Context->CharTy);
572 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
573 Exp->getSelector().getName().size(),
574 false, argType, SourceLocation(),
575 SourceLocation()));
576 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
577 &SelExprs[0], SelExprs.size());
578 MsgExprs.push_back(SelExp);
579
580 // Now push any user supplied arguments.
581 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
582 MsgExprs.push_back(Exp->getArg(i));
583 // We've transferred the ownership to MsgExprs. Null out the argument in
584 // the original expression, since we will delete it below.
585 Exp->setArg(i, 0);
586 }
587 CallExpr *MessExp = SynthesizeCallToFunctionDecl(MsgSendFunctionDecl,
588 &MsgExprs[0], MsgExprs.size());
589 // Now do the actual rewrite.
590 Rewrite.ReplaceStmt(Exp, MessExp);
591
Chris Lattnere64b7772007-10-24 16:57:36 +0000592 delete Exp;
Steve Naroff934f2762007-10-24 22:48:43 +0000593 return MessExp;
Steve Naroffebf2b562007-10-23 23:50:29 +0000594}
595
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000596/// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
597/// an objective-c class with ivars.
598void RewriteTest::SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
599 std::string &Result) {
600 assert(CDecl && "Class missing in SynthesizeObjcInternalStruct");
601 assert(CDecl->getName() && "Name missing in SynthesizeObjcInternalStruct");
Fariborz Jahanian212b7682007-10-31 23:08:24 +0000602 // Do not synthesize more than once.
603 if (ObjcSynthesizedStructs.count(CDecl))
604 return;
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000605 ObjcInterfaceDecl *RCDecl = CDecl->getSuperClass();
606 if (RCDecl && !ObjcSynthesizedStructs.count(RCDecl)) {
607 // Do it for the root
608 SynthesizeObjcInternalStruct(RCDecl, Result);
609 }
610
611 int NumIvars = CDecl->getIntfDeclNumIvars();
Fariborz Jahanianaff56d02007-10-31 22:57:04 +0000612 // If no ivars and no root or if its root, directly or indirectly,
Fariborz Jahanianf1de0ca2007-10-31 23:53:01 +0000613 // have no ivars (thus not synthesized) then no need to synthesize this class.
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000614 if (NumIvars <= 0 && (!RCDecl || !ObjcSynthesizedStructs.count(RCDecl)))
615 return;
616
617 Result += "\nstruct _interface_";
618 Result += CDecl->getName();
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000619 if (RCDecl && ObjcSynthesizedStructs.count(RCDecl)) {
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +0000620 Result += " {\n";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000621 Result += "\tstruct _interface_";
622 Result += RCDecl->getName();
623 Result += " _";
624 Result += RCDecl->getName();
625 Result += ";\n";
626 }
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +0000627 else
628 Result += " {";
Steve Naroff8749be52007-10-31 22:11:35 +0000629
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +0000630 if (NumIvars > 0) {
631 SourceLocation LocStart = CDecl->getLocStart();
632 SourceLocation LocEnd = CDecl->getLocEnd();
633
634 const char *startBuf = SM->getCharacterData(LocStart);
635 const char *endBuf = SM->getCharacterData(LocEnd);
636 startBuf = strchr(startBuf, '{');
637 assert((startBuf && endBuf)
638 && "SynthesizeObjcInternalStruct - malformed @interface");
639 startBuf++; // past '{'
640 while (startBuf < endBuf) {
641 if (*startBuf == '@') {
642 startBuf = strchr(startBuf, 'p');
643 // FIXME: presence of @public, etc. inside comment results in
644 // this transformation as well, which is still correct c-code.
645 if (!strncmp(startBuf, "public", strlen("public"))) {
646 startBuf += strlen("public");
647 Result += "/* @public */";
648 }
649 else if (!strncmp(startBuf, "private", strlen("private"))) {
650 startBuf += strlen("private");
651 Result += "/* @private */";
652 }
653 else if (!strncmp(startBuf, "protected", strlen("protected"))) {
654 startBuf += strlen("protected");
655 Result += "/* @protected */";
656 }
657 }
658 Result += *startBuf++;
659 }
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000660 }
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +0000661
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000662 Result += "};\n";
663 // Mark this struct as having been generated.
664 if (!ObjcSynthesizedStructs.insert(CDecl))
Fariborz Jahanianaff56d02007-10-31 22:57:04 +0000665 assert(false && "struct already synthesize- SynthesizeObjcInternalStruct");
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000666}
667
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000668// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
669/// class methods.
670void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
671 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000672 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000673 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +0000674 const char *ClassName,
675 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000676 static bool objc_impl_method = false;
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000677 if (NumMethods > 0 && !objc_impl_method) {
678 /* struct _objc_method {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000679 SEL _cmd;
680 char *method_types;
681 void *_imp;
682 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000683 */
Chris Lattner158ecb92007-10-25 17:07:24 +0000684 Result += "\nstruct _objc_method {\n";
685 Result += "\tSEL _cmd;\n";
686 Result += "\tchar *method_types;\n";
687 Result += "\tvoid *_imp;\n";
688 Result += "};\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000689
690 /* struct _objc_method_list {
691 struct _objc_method_list *next_method;
692 int method_count;
693 struct _objc_method method_list[];
694 }
695 */
696 Result += "\nstruct _objc_method_list {\n";
697 Result += "\tstruct _objc_method_list *next_method;\n";
698 Result += "\tint method_count;\n";
699 Result += "\tstruct _objc_method method_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000700 objc_impl_method = true;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000701 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000702 // Build _objc_method_list for class's methods if needed
703 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000704 Result += "\nstatic struct _objc_method_list _OBJC_";
Chris Lattner158ecb92007-10-25 17:07:24 +0000705 Result += prefix;
706 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
707 Result += "_METHODS_";
708 Result += ClassName;
709 Result += " __attribute__ ((section (\"__OBJC, __";
710 Result += IsInstanceMethod ? "inst" : "cls";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000711 Result += "_meth\")))= ";
712 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
713
714 Result += "\t,{{(SEL)\"";
715 Result += Methods[0]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000716 std::string MethodTypeString;
717 Context->getObjcEncodingForMethodDecl(Methods[0], MethodTypeString);
718 Result += "\", \"";
719 Result += MethodTypeString;
720 Result += "\", 0}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000721 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000722 // TODO: Need method address as 3rd initializer.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000723 Result += "\t ,{(SEL)\"";
724 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000725 std::string MethodTypeString;
726 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
727 Result += "\", \"";
728 Result += MethodTypeString;
729 Result += "\", 0}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000730 }
731 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000732 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000733}
734
735/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
736void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
737 int NumProtocols,
738 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000739 const char *ClassName,
740 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000741 static bool objc_protocol_methods = false;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000742 if (NumProtocols > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000743 for (int i = 0; i < NumProtocols; i++) {
744 ObjcProtocolDecl *PDecl = Protocols[i];
745 // Output struct protocol_methods holder of method selector and type.
746 if (!objc_protocol_methods &&
747 (PDecl->getNumInstanceMethods() > 0
748 || PDecl->getNumClassMethods() > 0)) {
749 /* struct protocol_methods {
750 SEL _cmd;
751 char *method_types;
752 }
753 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000754 Result += "\nstruct protocol_methods {\n";
755 Result += "\tSEL _cmd;\n";
756 Result += "\tchar *method_types;\n";
757 Result += "};\n";
758
759 /* struct _objc_protocol_method_list {
760 int protocol_method_count;
761 struct protocol_methods protocols[];
762 }
763 */
764 Result += "\nstruct _objc_protocol_method_list {\n";
765 Result += "\tint protocol_method_count;\n";
766 Result += "\tstruct protocol_methods protocols[];\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000767 objc_protocol_methods = true;
768 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000769
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000770 // Output instance methods declared in this protocol.
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000771 int NumMethods = PDecl->getNumInstanceMethods();
772 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000773 Result += "\nstatic struct _objc_protocol_method_list "
774 "_OBJC_PROTOCOL_INSTANCE_METHODS_";
775 Result += PDecl->getName();
776 Result += " __attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
777 "{\n\t" + utostr(NumMethods) + "\n";
778
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000779 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000780 Result += "\t,{{(SEL)\"";
781 Result += Methods[0]->getSelector().getName().c_str();
782 Result += "\", \"\"}\n";
783
784 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000785 Result += "\t ,{(SEL)\"";
786 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000787 std::string MethodTypeString;
788 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
789 Result += "\", \"";
790 Result += MethodTypeString;
791 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000792 }
793 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000794 }
795
796 // Output class methods declared in this protocol.
797 NumMethods = PDecl->getNumClassMethods();
798 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000799 Result += "\nstatic struct _objc_protocol_method_list "
800 "_OBJC_PROTOCOL_CLASS_METHODS_";
801 Result += PDecl->getName();
802 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
803 "{\n\t";
804 Result += utostr(NumMethods);
805 Result += "\n";
806
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000807 ObjcMethodDecl **Methods = PDecl->getClassMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000808 Result += "\t,{{(SEL)\"";
809 Result += Methods[0]->getSelector().getName().c_str();
810 Result += "\", \"\"}\n";
811
812 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000813 Result += "\t ,{(SEL)\"";
814 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000815 std::string MethodTypeString;
816 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
817 Result += "\", \"";
818 Result += MethodTypeString;
819 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000820 }
821 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000822 }
823 // Output:
824 /* struct _objc_protocol {
825 // Objective-C 1.0 extensions
826 struct _objc_protocol_extension *isa;
827 char *protocol_name;
828 struct _objc_protocol **protocol_list;
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000829 struct _objc_protocol_method_list *instance_methods;
830 struct _objc_protocol_method_list *class_methods;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000831 };
832 */
833 static bool objc_protocol = false;
834 if (!objc_protocol) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000835 Result += "\nstruct _objc_protocol {\n";
836 Result += "\tstruct _objc_protocol_extension *isa;\n";
837 Result += "\tchar *protocol_name;\n";
838 Result += "\tstruct _objc_protocol **protocol_list;\n";
839 Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
840 Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
841 Result += "};\n";
842
843 /* struct _objc_protocol_list {
844 struct _objc_protocol_list *next;
845 int protocol_count;
846 struct _objc_protocol *class_protocols[];
847 }
848 */
849 Result += "\nstruct _objc_protocol_list {\n";
850 Result += "\tstruct _objc_protocol_list *next;\n";
851 Result += "\tint protocol_count;\n";
852 Result += "\tstruct _objc_protocol *class_protocols[];\n";
853 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000854 objc_protocol = true;
855 }
856
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000857 Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
858 Result += PDecl->getName();
859 Result += " __attribute__ ((section (\"__OBJC, __protocol\")))= "
860 "{\n\t0, \"";
861 Result += PDecl->getName();
862 Result += "\", 0, ";
863 if (PDecl->getInstanceMethods() > 0) {
864 Result += "&_OBJC_PROTOCOL_INSTANCE_METHODS_";
865 Result += PDecl->getName();
866 Result += ", ";
867 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000868 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000869 Result += "0, ";
870 if (PDecl->getClassMethods() > 0) {
871 Result += "&_OBJC_PROTOCOL_CLASS_METHODS_";
872 Result += PDecl->getName();
873 Result += "\n";
874 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000875 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000876 Result += "0\n";
877 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000878 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000879 // Output the top lovel protocol meta-data for the class.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000880 Result += "\nstatic struct _objc_protocol_list _OBJC_";
881 Result += prefix;
882 Result += "_PROTOCOLS_";
883 Result += ClassName;
884 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
885 "{\n\t0, ";
886 Result += utostr(NumProtocols);
887 Result += "\n";
888
889 Result += "\t,{&_OBJC_PROTOCOL_";
890 Result += Protocols[0]->getName();
891 Result += " \n";
892
893 for (int i = 1; i < NumProtocols; i++) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000894 ObjcProtocolDecl *PDecl = Protocols[i];
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000895 Result += "\t ,&_OBJC_PROTOCOL_";
896 Result += PDecl->getName();
897 Result += "\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000898 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000899 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000900 }
901}
902
903/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
904/// implementation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000905void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl,
906 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000907 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
908 // Find category declaration for this implementation.
909 ObjcCategoryDecl *CDecl;
910 for (CDecl = ClassDecl->getCategoryList(); CDecl;
911 CDecl = CDecl->getNextClassCategory())
912 if (CDecl->getIdentifier() == IDecl->getIdentifier())
913 break;
914 assert(CDecl && "RewriteObjcCategoryImplDecl - bad category");
915
916 char *FullCategoryName = (char*)alloca(
917 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
918 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
919
920 // Build _objc_method_list for class's instance methods if needed
921 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
922 IDecl->getNumInstanceMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000923 true,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000924 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000925
926 // Build _objc_method_list for class's class methods if needed
927 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
928 IDecl->getNumClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000929 false,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000930 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000931
932 // Protocols referenced in class declaration?
933 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
934 CDecl->getNumReferencedProtocols(),
935 "CATEGORY",
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000936 FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000937
938 /* struct _objc_category {
939 char *category_name;
940 char *class_name;
941 struct _objc_method_list *instance_methods;
942 struct _objc_method_list *class_methods;
943 struct _objc_protocol_list *protocols;
944 // Objective-C 1.0 extensions
945 uint32_t size; // sizeof (struct _objc_category)
946 struct _objc_property_list *instance_properties; // category's own
947 // @property decl.
948 };
949 */
950
951 static bool objc_category = false;
952 if (!objc_category) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000953 Result += "\nstruct _objc_category {\n";
954 Result += "\tchar *category_name;\n";
955 Result += "\tchar *class_name;\n";
956 Result += "\tstruct _objc_method_list *instance_methods;\n";
957 Result += "\tstruct _objc_method_list *class_methods;\n";
958 Result += "\tstruct _objc_protocol_list *protocols;\n";
959 Result += "\tunsigned int size;\n";
960 Result += "\tstruct _objc_property_list *instance_properties;\n";
961 Result += "};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000962 objc_category = true;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000963 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000964 Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
965 Result += FullCategoryName;
966 Result += " __attribute__ ((section (\"__OBJC, __category\")))= {\n\t\"";
967 Result += IDecl->getName();
968 Result += "\"\n\t, \"";
969 Result += ClassDecl->getName();
970 Result += "\"\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000971
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000972 if (IDecl->getNumInstanceMethods() > 0) {
973 Result += "\t, (struct _objc_method_list *)"
974 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
975 Result += FullCategoryName;
976 Result += "\n";
977 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000978 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000979 Result += "\t, 0\n";
980 if (IDecl->getNumClassMethods() > 0) {
981 Result += "\t, (struct _objc_method_list *)"
982 "&_OBJC_CATEGORY_CLASS_METHODS_";
983 Result += FullCategoryName;
984 Result += "\n";
985 }
986 else
987 Result += "\t, 0\n";
988
989 if (CDecl->getNumReferencedProtocols() > 0) {
990 Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
991 Result += FullCategoryName;
992 Result += "\n";
993 }
994 else
995 Result += "\t, 0\n";
996 Result += "\t, sizeof(struct _objc_category), 0\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000997}
998
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000999/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
1000/// ivar offset.
1001void RewriteTest::SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
1002 ObjcIvarDecl *ivar,
1003 std::string &Result) {
1004 Result += "offsetof(struct _interface_";
1005 Result += IDecl->getName();
1006 Result += ", ";
1007 Result += ivar->getName();
1008 Result += ")";
1009}
1010
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001011//===----------------------------------------------------------------------===//
1012// Meta Data Emission
1013//===----------------------------------------------------------------------===//
1014
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001015void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
1016 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001017 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
1018
1019 // Build _objc_ivar_list metadata for classes ivars if needed
1020 int NumIvars = IDecl->getImplDeclNumIvars() > 0
1021 ? IDecl->getImplDeclNumIvars()
1022 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
1023
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00001024 SynthesizeObjcInternalStruct(CDecl, Result);
1025
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001026 if (NumIvars > 0) {
1027 static bool objc_ivar = false;
1028 if (!objc_ivar) {
1029 /* struct _objc_ivar {
1030 char *ivar_name;
1031 char *ivar_type;
1032 int ivar_offset;
1033 };
1034 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001035 Result += "\nstruct _objc_ivar {\n";
1036 Result += "\tchar *ivar_name;\n";
1037 Result += "\tchar *ivar_type;\n";
1038 Result += "\tint ivar_offset;\n";
1039 Result += "};\n";
1040
1041 /* struct _objc_ivar_list {
1042 int ivar_count;
1043 struct _objc_ivar ivar_list[];
1044 };
1045 */
1046 Result += "\nstruct _objc_ivar_list {\n";
1047 Result += "\tint ivar_count;\n";
1048 Result += "\tstruct _objc_ivar ivar_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001049 objc_ivar = true;
1050 }
1051
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001052 Result += "\nstatic struct _objc_ivar_list _OBJC_INSTANCE_VARIABLES_";
1053 Result += IDecl->getName();
1054 Result += " __attribute__ ((section (\"__OBJC, __instance_vars\")))= "
1055 "{\n\t";
1056 Result += utostr(NumIvars);
1057 Result += "\n";
1058
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001059 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
1060 ? IDecl->getImplDeclIVars()
1061 : CDecl->getIntfDeclIvars();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001062 Result += "\t,{{\"";
1063 Result += Ivars[0]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +00001064 Result += "\", \"";
1065 std::string StrEncoding;
1066 Context->getObjcEncodingForType(Ivars[0]->getType(), StrEncoding);
1067 Result += StrEncoding;
1068 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001069 SynthesizeIvarOffsetComputation(IDecl, Ivars[0], Result);
1070 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001071 for (int i = 1; i < NumIvars; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001072 Result += "\t ,{\"";
1073 Result += Ivars[i]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +00001074 Result += "\", \"";
1075 std::string StrEncoding;
1076 Context->getObjcEncodingForType(Ivars[i]->getType(), StrEncoding);
1077 Result += StrEncoding;
1078 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001079 SynthesizeIvarOffsetComputation(IDecl, Ivars[i], Result);
1080 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001081 }
1082
1083 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001084 }
1085
1086 // Build _objc_method_list for class's instance methods if needed
1087 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
1088 IDecl->getNumInstanceMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001089 true,
1090 "", IDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001091
1092 // Build _objc_method_list for class's class methods if needed
1093 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +00001094 IDecl->getNumClassMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001095 false,
1096 "", IDecl->getName(), Result);
1097
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001098 // Protocols referenced in class declaration?
1099 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
1100 CDecl->getNumIntfRefProtocols(),
1101 "CLASS",
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001102 CDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001103
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001104
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001105 // Declaration of class/meta-class metadata
1106 /* struct _objc_class {
1107 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001108 const char *super_class_name;
1109 char *name;
1110 long version;
1111 long info;
1112 long instance_size;
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001113 struct _objc_ivar_list *ivars;
1114 struct _objc_method_list *methods;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001115 struct objc_cache *cache;
1116 struct objc_protocol_list *protocols;
1117 const char *ivar_layout;
1118 struct _objc_class_ext *ext;
1119 };
1120 */
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001121 static bool objc_class = false;
1122 if (!objc_class) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001123 Result += "\nstruct _objc_class {\n";
1124 Result += "\tstruct _objc_class *isa;\n";
1125 Result += "\tconst char *super_class_name;\n";
1126 Result += "\tchar *name;\n";
1127 Result += "\tlong version;\n";
1128 Result += "\tlong info;\n";
1129 Result += "\tlong instance_size;\n";
1130 Result += "\tstruct _objc_ivar_list *ivars;\n";
1131 Result += "\tstruct _objc_method_list *methods;\n";
1132 Result += "\tstruct objc_cache *cache;\n";
1133 Result += "\tstruct _objc_protocol_list *protocols;\n";
1134 Result += "\tconst char *ivar_layout;\n";
1135 Result += "\tstruct _objc_class_ext *ext;\n";
1136 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001137 objc_class = true;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001138 }
1139
1140 // Meta-class metadata generation.
1141 ObjcInterfaceDecl *RootClass = 0;
1142 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
1143 while (SuperClass) {
1144 RootClass = SuperClass;
1145 SuperClass = SuperClass->getSuperClass();
1146 }
1147 SuperClass = CDecl->getSuperClass();
1148
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001149 Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
1150 Result += CDecl->getName();
1151 Result += " __attribute__ ((section (\"__OBJC, __meta_class\")))= "
1152 "{\n\t(struct _objc_class *)\"";
1153 Result += (RootClass ? RootClass->getName() : CDecl->getName());
1154 Result += "\"";
1155
1156 if (SuperClass) {
1157 Result += ", \"";
1158 Result += SuperClass->getName();
1159 Result += "\", \"";
1160 Result += CDecl->getName();
1161 Result += "\"";
1162 }
1163 else {
1164 Result += ", 0, \"";
1165 Result += CDecl->getName();
1166 Result += "\"";
1167 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001168 // TODO: 'ivars' field for root class is currently set to 0.
1169 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001170 Result += ", 0,2, sizeof(struct _objc_class), 0";
1171 if (CDecl->getNumClassMethods() > 0) {
1172 Result += "\n\t, &_OBJC_CLASS_METHODS_";
1173 Result += CDecl->getName();
1174 Result += "\n";
1175 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001176 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001177 Result += ", 0\n";
1178 if (CDecl->getNumIntfRefProtocols() > 0) {
1179 Result += "\t,0, &_OBJC_CLASS_PROTOCOLS_";
1180 Result += CDecl->getName();
1181 Result += ",0,0\n";
1182 }
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001183 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001184 Result += "\t,0,0,0,0\n";
1185 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001186
1187 // class metadata generation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001188 Result += "\nstatic struct _objc_class _OBJC_CLASS_";
1189 Result += CDecl->getName();
1190 Result += " __attribute__ ((section (\"__OBJC, __class\")))= "
1191 "{\n\t&_OBJC_METACLASS_";
1192 Result += CDecl->getName();
1193 if (SuperClass) {
1194 Result += ", \"";
1195 Result += SuperClass->getName();
1196 Result += "\", \"";
1197 Result += CDecl->getName();
1198 Result += "\"";
1199 }
1200 else {
1201 Result += ", 0, \"";
1202 Result += CDecl->getName();
1203 Result += "\"";
1204 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001205 // 'info' field is initialized to CLS_CLASS(1) for class
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00001206 Result += ", 0,1";
1207 if (!ObjcSynthesizedStructs.count(CDecl))
1208 Result += ",0";
1209 else {
1210 // class has size. Must synthesize its size.
1211 Result += ",sizeof(struct _interface_";
1212 Result += CDecl->getName();
1213 Result += ")";
1214 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001215 if (NumIvars > 0) {
1216 Result += ", &_OBJC_INSTANCE_VARIABLES_";
1217 Result += CDecl->getName();
1218 Result += "\n\t";
1219 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001220 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001221 Result += ",0";
1222 if (IDecl->getNumInstanceMethods() > 0) {
1223 Result += ", &_OBJC_INSTANCE_METHODS_";
1224 Result += CDecl->getName();
1225 Result += ", 0\n\t";
1226 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001227 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001228 Result += ",0,0";
1229 if (CDecl->getNumIntfRefProtocols() > 0) {
1230 Result += ", &_OBJC_CLASS_PROTOCOLS_";
1231 Result += CDecl->getName();
1232 Result += ", 0,0\n";
1233 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001234 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001235 Result += ",0,0,0\n";
1236 Result += "};\n";
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001237}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001238
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001239void RewriteTest::WriteObjcMetaData(std::string &Result) {
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001240 int ClsDefCount = ClassImplementation.size();
1241 int CatDefCount = CategoryImplementation.size();
1242 if (ClsDefCount == 0 && CatDefCount == 0)
1243 return;
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001244
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001245 // TODO: This is temporary until we decide how to access objc types in a
1246 // c program
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001247 Result += "#include <Objc/objc.h>\n";
1248 // This is needed for use of offsetof
1249 Result += "#include <stddef.h>\n";
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001250
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001251 // For each implemented class, write out all its meta data.
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001252 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001253 RewriteObjcClassMetaData(ClassImplementation[i], Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001254
1255 // For each implemented category, write out all its meta data.
1256 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001257 RewriteObjcCategoryImplDecl(CategoryImplementation[i], Result);
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001258
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001259 // Write objc_symtab metadata
1260 /*
1261 struct _objc_symtab
1262 {
1263 long sel_ref_cnt;
1264 SEL *refs;
1265 short cls_def_cnt;
1266 short cat_def_cnt;
1267 void *defs[cls_def_cnt + cat_def_cnt];
1268 };
1269 */
1270
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001271 Result += "\nstruct _objc_symtab {\n";
1272 Result += "\tlong sel_ref_cnt;\n";
1273 Result += "\tSEL *refs;\n";
1274 Result += "\tshort cls_def_cnt;\n";
1275 Result += "\tshort cat_def_cnt;\n";
1276 Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
1277 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001278
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001279 Result += "static struct _objc_symtab "
1280 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n";
1281 Result += "\t0, 0, " + utostr(ClsDefCount)
1282 + ", " + utostr(CatDefCount) + "\n";
1283 for (int i = 0; i < ClsDefCount; i++) {
1284 Result += "\t,&_OBJC_CLASS_";
1285 Result += ClassImplementation[i]->getName();
1286 Result += "\n";
1287 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001288
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001289 for (int i = 0; i < CatDefCount; i++) {
1290 Result += "\t,&_OBJC_CATEGORY_";
1291 Result += CategoryImplementation[i]->getClassInterface()->getName();
1292 Result += "_";
1293 Result += CategoryImplementation[i]->getName();
1294 Result += "\n";
1295 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001296
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001297 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001298
1299 // Write objc_module metadata
1300
1301 /*
1302 struct _objc_module {
1303 long version;
1304 long size;
1305 const char *name;
1306 struct _objc_symtab *symtab;
1307 }
1308 */
1309
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001310 Result += "\nstruct _objc_module {\n";
1311 Result += "\tlong version;\n";
1312 Result += "\tlong size;\n";
1313 Result += "\tconst char *name;\n";
1314 Result += "\tstruct _objc_symtab *symtab;\n";
1315 Result += "};\n\n";
1316 Result += "static struct _objc_module "
1317 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001318 Result += "\t" + utostr(OBJC_ABI_VERSION) +
1319 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001320 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001321}
Chris Lattner311ff022007-10-16 22:36:42 +00001322