blob: be09eede3106a96349af28b739be0d3acc678eae [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 Naroffebf2b562007-10-23 23:50:29 +000036
37 FunctionDecl *MsgSendFunctionDecl;
38 FunctionDecl *GetClassFunctionDecl;
Steve Naroff934f2762007-10-24 22:48:43 +000039 FunctionDecl *SelGetUidFunctionDecl;
Steve Naroffebf2b562007-10-23 23:50:29 +000040
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000041 static const int OBJC_ABI_VERSION =7 ;
Chris Lattner77cd2a02007-10-11 00:43:27 +000042 public:
Chris Lattner01c57482007-10-17 22:35:30 +000043 void Initialize(ASTContext &context, unsigned mainFileID) {
44 Context = &context;
45 SM = &Context->SourceMgr;
Chris Lattner8a12c272007-10-11 18:38:32 +000046 MainFileID = mainFileID;
Steve Naroffebf2b562007-10-23 23:50:29 +000047 MsgSendFunctionDecl = 0;
Steve Naroffc0006092007-10-24 01:09:48 +000048 GetClassFunctionDecl = 0;
Steve Naroff934f2762007-10-24 22:48:43 +000049 SelGetUidFunctionDecl = 0;
Chris Lattner01c57482007-10-17 22:35:30 +000050 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattner77cd2a02007-10-11 00:43:27 +000051 }
Chris Lattner8a12c272007-10-11 18:38:32 +000052
Chris Lattnerf04da132007-10-24 17:06:59 +000053 // Top Level Driver code.
54 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner2c64b7b2007-10-16 21:07:07 +000055 void HandleDeclInMainFile(Decl *D);
Chris Lattnerf04da132007-10-24 17:06:59 +000056 ~RewriteTest();
57
58 // Syntactic Rewriting.
Chris Lattner2c64b7b2007-10-16 21:07:07 +000059 void RewriteInclude(SourceLocation Loc);
Chris Lattnerf04da132007-10-24 17:06:59 +000060 void RewriteTabs();
61 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Steve Naroffbef11852007-10-26 20:53:56 +000062 void RewriteInterfaceDecl(ObjcInterfaceDecl *Dcl);
Chris Lattner311ff022007-10-16 22:36:42 +000063
Chris Lattnerf04da132007-10-24 17:06:59 +000064 // Expression Rewriting.
Chris Lattnere64b7772007-10-24 16:57:36 +000065 Stmt *RewriteFunctionBody(Stmt *S);
66 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
67 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroff934f2762007-10-24 22:48:43 +000068 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
69 Expr **args, unsigned nargs);
Chris Lattnerf04da132007-10-24 17:06:59 +000070 // Metadata emission.
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000071 void HandleObjcMetaDataEmission();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000072 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
73 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000074
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000075 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl,
76 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000077
78 void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
79 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +000080 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000081 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +000082 const char *ClassName,
83 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000084
85 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
86 int NumProtocols,
87 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000088 const char *ClassName,
89 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000090 void SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
91 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000092 void SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
93 ObjcIvarDecl *ivar,
94 std::string &Result);
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000095 void WriteObjcMetaData(std::string &Result);
Chris Lattner77cd2a02007-10-11 00:43:27 +000096 };
97}
98
Chris Lattner8a12c272007-10-11 18:38:32 +000099ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattner77cd2a02007-10-11 00:43:27 +0000100
Chris Lattnerf04da132007-10-24 17:06:59 +0000101//===----------------------------------------------------------------------===//
102// Top Level Driver Code
103//===----------------------------------------------------------------------===//
104
Chris Lattner8a12c272007-10-11 18:38:32 +0000105void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000106 // Two cases: either the decl could be in the main file, or it could be in a
107 // #included file. If the former, rewrite it now. If the later, check to see
108 // if we rewrote the #include/#import.
109 SourceLocation Loc = D->getLocation();
110 Loc = SM->getLogicalLoc(Loc);
111
112 // If this is for a builtin, ignore it.
113 if (Loc.isInvalid()) return;
114
Steve Naroffebf2b562007-10-23 23:50:29 +0000115 // Look for built-in declarations that we need to refer during the rewrite.
116 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroffc0006092007-10-24 01:09:48 +0000117 if (strcmp(FD->getName(), "objc_msgSend") == 0)
Steve Naroffebf2b562007-10-23 23:50:29 +0000118 MsgSendFunctionDecl = FD;
Steve Naroffc0006092007-10-24 01:09:48 +0000119 else if (strcmp(FD->getName(), "objc_getClass") == 0)
Steve Naroffebf2b562007-10-23 23:50:29 +0000120 GetClassFunctionDecl = FD;
Steve Naroff934f2762007-10-24 22:48:43 +0000121 else if (strcmp(FD->getName(), "sel_getUid") == 0)
122 SelGetUidFunctionDecl = FD;
Steve Naroffbef11852007-10-26 20:53:56 +0000123 } else if (ObjcInterfaceDecl *MD = dyn_cast<ObjcInterfaceDecl>(D)) {
124 RewriteInterfaceDecl(MD);
Steve Naroffebf2b562007-10-23 23:50:29 +0000125 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000126 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000127 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
128 return HandleDeclInMainFile(D);
129
Chris Lattnerf04da132007-10-24 17:06:59 +0000130 // Otherwise, see if there is a #import in the main file that should be
131 // rewritten.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000132 RewriteInclude(Loc);
133}
134
Chris Lattnerf04da132007-10-24 17:06:59 +0000135/// HandleDeclInMainFile - This is called for each top-level decl defined in the
136/// main file of the input.
137void RewriteTest::HandleDeclInMainFile(Decl *D) {
138 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
139 if (Stmt *Body = FD->getBody())
140 FD->setBody(RewriteFunctionBody(Body));
141
142 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
143 ClassImplementation.push_back(CI);
144 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
145 CategoryImplementation.push_back(CI);
146 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
147 RewriteForwardClassDecl(CD);
148 // Nothing yet.
149}
150
151RewriteTest::~RewriteTest() {
152 // Get the top-level buffer that this corresponds to.
153 RewriteTabs();
154
155 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
156 // we are done.
157 if (const RewriteBuffer *RewriteBuf =
158 Rewrite.getRewriteBufferFor(MainFileID)) {
159 printf("Changed:\n");
160 std::string S(RewriteBuf->begin(), RewriteBuf->end());
161 printf("%s\n", S.c_str());
162 } else {
163 printf("No changes\n");
164 }
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000165
166}
167
168/// HandleObjcMetaDataEmission - main routine to generate objective-c's
169/// metadata.
170void RewriteTest::HandleObjcMetaDataEmission() {
Chris Lattnerf04da132007-10-24 17:06:59 +0000171 // Rewrite Objective-c meta data*
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000172 std::string ResultStr;
173 WriteObjcMetaData(ResultStr);
174 // For now just print the string out.
175 printf("%s", ResultStr.c_str());
Chris Lattnerf04da132007-10-24 17:06:59 +0000176}
177
178//===----------------------------------------------------------------------===//
179// Syntactic (non-AST) Rewriting Code
180//===----------------------------------------------------------------------===//
181
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000182void RewriteTest::RewriteInclude(SourceLocation Loc) {
183 // Rip up the #include stack to the main file.
184 SourceLocation IncLoc = Loc, NextLoc = Loc;
185 do {
186 IncLoc = Loc;
187 Loc = SM->getLogicalLoc(NextLoc);
188 NextLoc = SM->getIncludeLoc(Loc);
189 } while (!NextLoc.isInvalid());
190
191 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
192 // IncLoc indicates the header that was included if it is useful.
193 IncLoc = SM->getLogicalLoc(IncLoc);
194 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
195 Loc == LastIncLoc)
196 return;
197 LastIncLoc = Loc;
198
199 unsigned IncCol = SM->getColumnNumber(Loc);
200 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
201
202 // Replace the #import with #include.
203 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
204}
205
Chris Lattnerf04da132007-10-24 17:06:59 +0000206void RewriteTest::RewriteTabs() {
207 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
208 const char *MainBufStart = MainBuf.first;
209 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000210
Chris Lattnerf04da132007-10-24 17:06:59 +0000211 // Loop over the whole file, looking for tabs.
212 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
213 if (*BufPtr != '\t')
214 continue;
215
216 // Okay, we found a tab. This tab will turn into at least one character,
217 // but it depends on which 'virtual column' it is in. Compute that now.
218 unsigned VCol = 0;
219 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
220 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
221 ++VCol;
222
223 // Okay, now that we know the virtual column, we know how many spaces to
224 // insert. We assume 8-character tab-stops.
225 unsigned Spaces = 8-(VCol & 7);
226
227 // Get the location of the tab.
228 SourceLocation TabLoc =
229 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
230
231 // Rewrite the single tab character into a sequence of spaces.
232 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
233 }
Chris Lattner8a12c272007-10-11 18:38:32 +0000234}
235
236
Chris Lattnerf04da132007-10-24 17:06:59 +0000237void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
238 int numDecls = ClassDecl->getNumForwardDecls();
239 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
240
241 // Get the start location and compute the semi location.
242 SourceLocation startLoc = ClassDecl->getLocation();
243 const char *startBuf = SM->getCharacterData(startLoc);
244 const char *semiPtr = strchr(startBuf, ';');
245
246 // Translate to typedef's that forward reference structs with the same name
247 // as the class. As a convenience, we include the original declaration
248 // as a comment.
249 std::string typedefString;
250 typedefString += "// ";
Steve Naroff934f2762007-10-24 22:48:43 +0000251 typedefString.append(startBuf, semiPtr-startBuf+1);
252 typedefString += "\n";
253 for (int i = 0; i < numDecls; i++) {
254 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
255 typedefString += "typedef struct ";
256 typedefString += ForwardDecl->getName();
257 typedefString += " ";
258 typedefString += ForwardDecl->getName();
259 typedefString += ";\n";
260 }
261
262 // Replace the @class with typedefs corresponding to the classes.
263 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
264 typedefString.c_str(), typedefString.size());
Chris Lattnerf04da132007-10-24 17:06:59 +0000265}
266
Steve Naroffbef11852007-10-26 20:53:56 +0000267void RewriteTest::RewriteInterfaceDecl(ObjcInterfaceDecl *ClassDecl) {
Steve Narofff908a872007-10-30 02:23:23 +0000268
269 SourceLocation LocStart = ClassDecl->getLocStart();
270 SourceLocation LocEnd = ClassDecl->getLocEnd();
271
272 const char *startBuf = SM->getCharacterData(LocStart);
273 const char *endBuf = SM->getCharacterData(LocEnd);
274
Steve Naroff2feac5e2007-10-30 03:43:13 +0000275 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM);
Steve Narofff908a872007-10-30 02:23:23 +0000276
277 std::string ResultStr;
278 SynthesizeObjcInternalStruct(ClassDecl, ResultStr);
279
Steve Naroff2feac5e2007-10-30 03:43:13 +0000280 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
Steve Narofff908a872007-10-30 02:23:23 +0000281 ResultStr.c_str(), ResultStr.size());
282
Steve Naroffbef11852007-10-26 20:53:56 +0000283 int nInstanceMethods = ClassDecl->getNumInstanceMethods();
284 ObjcMethodDecl **instanceMethods = ClassDecl->getInstanceMethods();
285
286 for (int i = 0; i < nInstanceMethods; i++) {
287 ObjcMethodDecl *instanceMethod = instanceMethods[i];
288 SourceLocation Loc = instanceMethod->getLocStart();
289
290 Rewrite.ReplaceText(Loc, 0, "// ", 3);
291
292 // FIXME: handle methods that are declared across multiple lines.
293 }
294 int nClassMethods = ClassDecl->getNumClassMethods();
295 ObjcMethodDecl **classMethods = ClassDecl->getClassMethods();
296
297 for (int i = 0; i < nClassMethods; i++) {
298 ObjcMethodDecl *classMethod = classMethods[i];
299 SourceLocation Loc = classMethod->getLocStart();
300
301 Rewrite.ReplaceText(Loc, 0, "// ", 3);
302
303 // FIXME: handle methods that are declared across multiple lines.
304 }
Steve Naroff2feac5e2007-10-30 03:43:13 +0000305 // Lastly, comment out the @end.
306 Rewrite.ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3);
Steve Naroffbef11852007-10-26 20:53:56 +0000307}
308
Chris Lattnerf04da132007-10-24 17:06:59 +0000309//===----------------------------------------------------------------------===//
310// Function Body / Expression rewriting
311//===----------------------------------------------------------------------===//
312
Chris Lattnere64b7772007-10-24 16:57:36 +0000313Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner311ff022007-10-16 22:36:42 +0000314 // Otherwise, just rewrite all children.
315 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
316 CI != E; ++CI)
Chris Lattner50754772007-10-17 21:28:00 +0000317 if (*CI)
Chris Lattnere64b7772007-10-24 16:57:36 +0000318 *CI = RewriteFunctionBody(*CI);
Steve Naroffebf2b562007-10-23 23:50:29 +0000319
320 // Handle specific things.
321 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
322 return RewriteAtEncode(AtEncode);
323
Steve Naroff934f2762007-10-24 22:48:43 +0000324 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
325 // Before we rewrite it, put the original message expression in a comment.
326 SourceLocation startLoc = MessExpr->getLocStart();
327 SourceLocation endLoc = MessExpr->getLocEnd();
328
329 const char *startBuf = SM->getCharacterData(startLoc);
330 const char *endBuf = SM->getCharacterData(endLoc);
331
332 std::string messString;
333 messString += "// ";
334 messString.append(startBuf, endBuf-startBuf+1);
335 messString += "\n";
Steve Naroffbef11852007-10-26 20:53:56 +0000336
Steve Naroff934f2762007-10-24 22:48:43 +0000337 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
338 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
339 // Tried this, but it didn't work either...
Steve Naroffbef11852007-10-26 20:53:56 +0000340 Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffebf2b562007-10-23 23:50:29 +0000341 return RewriteMessageExpr(MessExpr);
Steve Naroff934f2762007-10-24 22:48:43 +0000342 }
Chris Lattnere64b7772007-10-24 16:57:36 +0000343 // Return this stmt unmodified.
344 return S;
Chris Lattner311ff022007-10-16 22:36:42 +0000345}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000346
Chris Lattnere64b7772007-10-24 16:57:36 +0000347Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattner01c57482007-10-17 22:35:30 +0000348 // Create a new string expression.
349 QualType StrType = Context->getPointerType(Context->CharTy);
Anders Carlsson85f9bce2007-10-29 05:01:08 +0000350 std::string StrEncoding;
351 Context->getObjcEncodingForType(Exp->getEncodedType(), StrEncoding);
352 Expr *Replacement = new StringLiteral(StrEncoding.c_str(),
353 StrEncoding.length(), false, StrType,
Chris Lattner01c57482007-10-17 22:35:30 +0000354 SourceLocation(), SourceLocation());
355 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattnere64b7772007-10-24 16:57:36 +0000356 delete Exp;
357 return Replacement;
Chris Lattner311ff022007-10-16 22:36:42 +0000358}
359
Steve Naroff934f2762007-10-24 22:48:43 +0000360CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
361 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffebf2b562007-10-23 23:50:29 +0000362 // Get the type, we will need to reference it in a couple spots.
Steve Naroff934f2762007-10-24 22:48:43 +0000363 QualType msgSendType = FD->getType();
Steve Naroffebf2b562007-10-23 23:50:29 +0000364
365 // Create a reference to the objc_msgSend() declaration.
Steve Naroff934f2762007-10-24 22:48:43 +0000366 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffebf2b562007-10-23 23:50:29 +0000367
368 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerf04da132007-10-24 17:06:59 +0000369 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffebf2b562007-10-23 23:50:29 +0000370 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
371
372 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattnere64b7772007-10-24 16:57:36 +0000373
Steve Naroff934f2762007-10-24 22:48:43 +0000374 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
375}
376
377Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
378 assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
379 assert(SelGetUidFunctionDecl && "Can't find sel_getUid() decl");
380 assert(GetClassFunctionDecl && "Can't find objc_getClass() decl");
381
382 // Synthesize a call to objc_msgSend().
383 llvm::SmallVector<Expr*, 8> MsgExprs;
384 IdentifierInfo *clsName = Exp->getClassName();
385
386 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
387 if (clsName) { // class message.
388 llvm::SmallVector<Expr*, 8> ClsExprs;
389 QualType argType = Context->getPointerType(Context->CharTy);
390 ClsExprs.push_back(new StringLiteral(clsName->getName(),
391 clsName->getLength(),
392 false, argType, SourceLocation(),
393 SourceLocation()));
394 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
395 &ClsExprs[0], ClsExprs.size());
396 MsgExprs.push_back(Cls);
397 } else // instance message.
398 MsgExprs.push_back(Exp->getReceiver());
399
400 // Create a call to sel_getUid("selName"), it will be the 2nd argument.
401 llvm::SmallVector<Expr*, 8> SelExprs;
402 QualType argType = Context->getPointerType(Context->CharTy);
403 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
404 Exp->getSelector().getName().size(),
405 false, argType, SourceLocation(),
406 SourceLocation()));
407 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
408 &SelExprs[0], SelExprs.size());
409 MsgExprs.push_back(SelExp);
410
411 // Now push any user supplied arguments.
412 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
413 MsgExprs.push_back(Exp->getArg(i));
414 // We've transferred the ownership to MsgExprs. Null out the argument in
415 // the original expression, since we will delete it below.
416 Exp->setArg(i, 0);
417 }
418 CallExpr *MessExp = SynthesizeCallToFunctionDecl(MsgSendFunctionDecl,
419 &MsgExprs[0], MsgExprs.size());
420 // Now do the actual rewrite.
421 Rewrite.ReplaceStmt(Exp, MessExp);
422
Chris Lattnere64b7772007-10-24 16:57:36 +0000423 delete Exp;
Steve Naroff934f2762007-10-24 22:48:43 +0000424 return MessExp;
Steve Naroffebf2b562007-10-23 23:50:29 +0000425}
426
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000427/// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
428/// an objective-c class with ivars.
429void RewriteTest::SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
430 std::string &Result) {
431 assert(CDecl && "Class missing in SynthesizeObjcInternalStruct");
432 assert(CDecl->getName() && "Name missing in SynthesizeObjcInternalStruct");
433 ObjcInterfaceDecl *RCDecl = CDecl->getSuperClass();
434 if (RCDecl && !ObjcSynthesizedStructs.count(RCDecl)) {
435 // Do it for the root
436 SynthesizeObjcInternalStruct(RCDecl, Result);
437 }
438
439 int NumIvars = CDecl->getIntfDeclNumIvars();
440 if (NumIvars <= 0 && (!RCDecl || !ObjcSynthesizedStructs.count(RCDecl)))
441 return;
442
443 Result += "\nstruct _interface_";
444 Result += CDecl->getName();
445 Result += " {\n";
446 if (RCDecl && ObjcSynthesizedStructs.count(RCDecl)) {
447 Result += "\tstruct _interface_";
448 Result += RCDecl->getName();
449 Result += " _";
450 Result += RCDecl->getName();
451 Result += ";\n";
452 }
453
454 ObjcIvarDecl **Ivars = CDecl->getIntfDeclIvars();
455 for (int i = 0; i < NumIvars; i++) {
456 Result += "\t";
457 std::string Name = Ivars[i]->getName();
458 Ivars[i]->getType().getAsStringInternal(Name);
459 Result += Name;
460 Result += ";\n";
461 }
462 Result += "};\n";
463 // Mark this struct as having been generated.
464 if (!ObjcSynthesizedStructs.insert(CDecl))
465 assert(true && "struct already synthesize- SynthesizeObjcInternalStruct");
466}
467
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000468// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
469/// class methods.
470void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
471 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000472 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000473 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +0000474 const char *ClassName,
475 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000476 static bool objc_impl_method = false;
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000477 if (NumMethods > 0 && !objc_impl_method) {
478 /* struct _objc_method {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000479 SEL _cmd;
480 char *method_types;
481 void *_imp;
482 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000483 */
Chris Lattner158ecb92007-10-25 17:07:24 +0000484 Result += "\nstruct _objc_method {\n";
485 Result += "\tSEL _cmd;\n";
486 Result += "\tchar *method_types;\n";
487 Result += "\tvoid *_imp;\n";
488 Result += "};\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000489
490 /* struct _objc_method_list {
491 struct _objc_method_list *next_method;
492 int method_count;
493 struct _objc_method method_list[];
494 }
495 */
496 Result += "\nstruct _objc_method_list {\n";
497 Result += "\tstruct _objc_method_list *next_method;\n";
498 Result += "\tint method_count;\n";
499 Result += "\tstruct _objc_method method_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000500 objc_impl_method = true;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000501 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000502 // Build _objc_method_list for class's methods if needed
503 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000504 Result += "\nstatic struct _objc_method_list _OBJC_";
Chris Lattner158ecb92007-10-25 17:07:24 +0000505 Result += prefix;
506 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
507 Result += "_METHODS_";
508 Result += ClassName;
509 Result += " __attribute__ ((section (\"__OBJC, __";
510 Result += IsInstanceMethod ? "inst" : "cls";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000511 Result += "_meth\")))= ";
512 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
513
514 Result += "\t,{{(SEL)\"";
515 Result += Methods[0]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000516 std::string MethodTypeString;
517 Context->getObjcEncodingForMethodDecl(Methods[0], MethodTypeString);
518 Result += "\", \"";
519 Result += MethodTypeString;
520 Result += "\", 0}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000521 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000522 // TODO: Need method address as 3rd initializer.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000523 Result += "\t ,{(SEL)\"";
524 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000525 std::string MethodTypeString;
526 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
527 Result += "\", \"";
528 Result += MethodTypeString;
529 Result += "\", 0}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000530 }
531 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000532 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000533}
534
535/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
536void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
537 int NumProtocols,
538 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000539 const char *ClassName,
540 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000541 static bool objc_protocol_methods = false;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000542 if (NumProtocols > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000543 for (int i = 0; i < NumProtocols; i++) {
544 ObjcProtocolDecl *PDecl = Protocols[i];
545 // Output struct protocol_methods holder of method selector and type.
546 if (!objc_protocol_methods &&
547 (PDecl->getNumInstanceMethods() > 0
548 || PDecl->getNumClassMethods() > 0)) {
549 /* struct protocol_methods {
550 SEL _cmd;
551 char *method_types;
552 }
553 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000554 Result += "\nstruct protocol_methods {\n";
555 Result += "\tSEL _cmd;\n";
556 Result += "\tchar *method_types;\n";
557 Result += "};\n";
558
559 /* struct _objc_protocol_method_list {
560 int protocol_method_count;
561 struct protocol_methods protocols[];
562 }
563 */
564 Result += "\nstruct _objc_protocol_method_list {\n";
565 Result += "\tint protocol_method_count;\n";
566 Result += "\tstruct protocol_methods protocols[];\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000567 objc_protocol_methods = true;
568 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000569
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000570 // Output instance methods declared in this protocol.
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000571 int NumMethods = PDecl->getNumInstanceMethods();
572 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000573 Result += "\nstatic struct _objc_protocol_method_list "
574 "_OBJC_PROTOCOL_INSTANCE_METHODS_";
575 Result += PDecl->getName();
576 Result += " __attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
577 "{\n\t" + utostr(NumMethods) + "\n";
578
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000579 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000580 Result += "\t,{{(SEL)\"";
581 Result += Methods[0]->getSelector().getName().c_str();
582 Result += "\", \"\"}\n";
583
584 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000585 Result += "\t ,{(SEL)\"";
586 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000587 std::string MethodTypeString;
588 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
589 Result += "\", \"";
590 Result += MethodTypeString;
591 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000592 }
593 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000594 }
595
596 // Output class methods declared in this protocol.
597 NumMethods = PDecl->getNumClassMethods();
598 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000599 Result += "\nstatic struct _objc_protocol_method_list "
600 "_OBJC_PROTOCOL_CLASS_METHODS_";
601 Result += PDecl->getName();
602 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
603 "{\n\t";
604 Result += utostr(NumMethods);
605 Result += "\n";
606
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000607 ObjcMethodDecl **Methods = PDecl->getClassMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000608 Result += "\t,{{(SEL)\"";
609 Result += Methods[0]->getSelector().getName().c_str();
610 Result += "\", \"\"}\n";
611
612 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000613 Result += "\t ,{(SEL)\"";
614 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000615 std::string MethodTypeString;
616 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
617 Result += "\", \"";
618 Result += MethodTypeString;
619 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000620 }
621 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000622 }
623 // Output:
624 /* struct _objc_protocol {
625 // Objective-C 1.0 extensions
626 struct _objc_protocol_extension *isa;
627 char *protocol_name;
628 struct _objc_protocol **protocol_list;
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000629 struct _objc_protocol_method_list *instance_methods;
630 struct _objc_protocol_method_list *class_methods;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000631 };
632 */
633 static bool objc_protocol = false;
634 if (!objc_protocol) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000635 Result += "\nstruct _objc_protocol {\n";
636 Result += "\tstruct _objc_protocol_extension *isa;\n";
637 Result += "\tchar *protocol_name;\n";
638 Result += "\tstruct _objc_protocol **protocol_list;\n";
639 Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
640 Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
641 Result += "};\n";
642
643 /* struct _objc_protocol_list {
644 struct _objc_protocol_list *next;
645 int protocol_count;
646 struct _objc_protocol *class_protocols[];
647 }
648 */
649 Result += "\nstruct _objc_protocol_list {\n";
650 Result += "\tstruct _objc_protocol_list *next;\n";
651 Result += "\tint protocol_count;\n";
652 Result += "\tstruct _objc_protocol *class_protocols[];\n";
653 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000654 objc_protocol = true;
655 }
656
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000657 Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
658 Result += PDecl->getName();
659 Result += " __attribute__ ((section (\"__OBJC, __protocol\")))= "
660 "{\n\t0, \"";
661 Result += PDecl->getName();
662 Result += "\", 0, ";
663 if (PDecl->getInstanceMethods() > 0) {
664 Result += "&_OBJC_PROTOCOL_INSTANCE_METHODS_";
665 Result += PDecl->getName();
666 Result += ", ";
667 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000668 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000669 Result += "0, ";
670 if (PDecl->getClassMethods() > 0) {
671 Result += "&_OBJC_PROTOCOL_CLASS_METHODS_";
672 Result += PDecl->getName();
673 Result += "\n";
674 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000675 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000676 Result += "0\n";
677 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000678 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000679 // Output the top lovel protocol meta-data for the class.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000680 Result += "\nstatic struct _objc_protocol_list _OBJC_";
681 Result += prefix;
682 Result += "_PROTOCOLS_";
683 Result += ClassName;
684 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
685 "{\n\t0, ";
686 Result += utostr(NumProtocols);
687 Result += "\n";
688
689 Result += "\t,{&_OBJC_PROTOCOL_";
690 Result += Protocols[0]->getName();
691 Result += " \n";
692
693 for (int i = 1; i < NumProtocols; i++) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000694 ObjcProtocolDecl *PDecl = Protocols[i];
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000695 Result += "\t ,&_OBJC_PROTOCOL_";
696 Result += PDecl->getName();
697 Result += "\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000698 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000699 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000700 }
701}
702
703/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
704/// implementation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000705void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl,
706 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000707 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
708 // Find category declaration for this implementation.
709 ObjcCategoryDecl *CDecl;
710 for (CDecl = ClassDecl->getCategoryList(); CDecl;
711 CDecl = CDecl->getNextClassCategory())
712 if (CDecl->getIdentifier() == IDecl->getIdentifier())
713 break;
714 assert(CDecl && "RewriteObjcCategoryImplDecl - bad category");
715
716 char *FullCategoryName = (char*)alloca(
717 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
718 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
719
720 // Build _objc_method_list for class's instance methods if needed
721 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
722 IDecl->getNumInstanceMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000723 true,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000724 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000725
726 // Build _objc_method_list for class's class methods if needed
727 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
728 IDecl->getNumClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000729 false,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000730 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000731
732 // Protocols referenced in class declaration?
733 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
734 CDecl->getNumReferencedProtocols(),
735 "CATEGORY",
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000736 FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000737
738 /* struct _objc_category {
739 char *category_name;
740 char *class_name;
741 struct _objc_method_list *instance_methods;
742 struct _objc_method_list *class_methods;
743 struct _objc_protocol_list *protocols;
744 // Objective-C 1.0 extensions
745 uint32_t size; // sizeof (struct _objc_category)
746 struct _objc_property_list *instance_properties; // category's own
747 // @property decl.
748 };
749 */
750
751 static bool objc_category = false;
752 if (!objc_category) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000753 Result += "\nstruct _objc_category {\n";
754 Result += "\tchar *category_name;\n";
755 Result += "\tchar *class_name;\n";
756 Result += "\tstruct _objc_method_list *instance_methods;\n";
757 Result += "\tstruct _objc_method_list *class_methods;\n";
758 Result += "\tstruct _objc_protocol_list *protocols;\n";
759 Result += "\tunsigned int size;\n";
760 Result += "\tstruct _objc_property_list *instance_properties;\n";
761 Result += "};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000762 objc_category = true;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000763 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000764 Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
765 Result += FullCategoryName;
766 Result += " __attribute__ ((section (\"__OBJC, __category\")))= {\n\t\"";
767 Result += IDecl->getName();
768 Result += "\"\n\t, \"";
769 Result += ClassDecl->getName();
770 Result += "\"\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000771
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000772 if (IDecl->getNumInstanceMethods() > 0) {
773 Result += "\t, (struct _objc_method_list *)"
774 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
775 Result += FullCategoryName;
776 Result += "\n";
777 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000778 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000779 Result += "\t, 0\n";
780 if (IDecl->getNumClassMethods() > 0) {
781 Result += "\t, (struct _objc_method_list *)"
782 "&_OBJC_CATEGORY_CLASS_METHODS_";
783 Result += FullCategoryName;
784 Result += "\n";
785 }
786 else
787 Result += "\t, 0\n";
788
789 if (CDecl->getNumReferencedProtocols() > 0) {
790 Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
791 Result += FullCategoryName;
792 Result += "\n";
793 }
794 else
795 Result += "\t, 0\n";
796 Result += "\t, sizeof(struct _objc_category), 0\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000797}
798
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000799/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
800/// ivar offset.
801void RewriteTest::SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
802 ObjcIvarDecl *ivar,
803 std::string &Result) {
804 Result += "offsetof(struct _interface_";
805 Result += IDecl->getName();
806 Result += ", ";
807 Result += ivar->getName();
808 Result += ")";
809}
810
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000811//===----------------------------------------------------------------------===//
812// Meta Data Emission
813//===----------------------------------------------------------------------===//
814
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000815void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
816 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000817 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
818
819 // Build _objc_ivar_list metadata for classes ivars if needed
820 int NumIvars = IDecl->getImplDeclNumIvars() > 0
821 ? IDecl->getImplDeclNumIvars()
822 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
823
Fariborz Jahanian4d733d32007-10-26 23:09:28 +0000824 SynthesizeObjcInternalStruct(CDecl, Result);
825
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000826 if (NumIvars > 0) {
827 static bool objc_ivar = false;
828 if (!objc_ivar) {
829 /* struct _objc_ivar {
830 char *ivar_name;
831 char *ivar_type;
832 int ivar_offset;
833 };
834 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000835 Result += "\nstruct _objc_ivar {\n";
836 Result += "\tchar *ivar_name;\n";
837 Result += "\tchar *ivar_type;\n";
838 Result += "\tint ivar_offset;\n";
839 Result += "};\n";
840
841 /* struct _objc_ivar_list {
842 int ivar_count;
843 struct _objc_ivar ivar_list[];
844 };
845 */
846 Result += "\nstruct _objc_ivar_list {\n";
847 Result += "\tint ivar_count;\n";
848 Result += "\tstruct _objc_ivar ivar_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000849 objc_ivar = true;
850 }
851
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000852 Result += "\nstatic struct _objc_ivar_list _OBJC_INSTANCE_VARIABLES_";
853 Result += IDecl->getName();
854 Result += " __attribute__ ((section (\"__OBJC, __instance_vars\")))= "
855 "{\n\t";
856 Result += utostr(NumIvars);
857 Result += "\n";
858
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000859 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
860 ? IDecl->getImplDeclIVars()
861 : CDecl->getIntfDeclIvars();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000862 Result += "\t,{{\"";
863 Result += Ivars[0]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +0000864 Result += "\", \"";
865 std::string StrEncoding;
866 Context->getObjcEncodingForType(Ivars[0]->getType(), StrEncoding);
867 Result += StrEncoding;
868 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000869 SynthesizeIvarOffsetComputation(IDecl, Ivars[0], Result);
870 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000871 for (int i = 1; i < NumIvars; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000872 Result += "\t ,{\"";
873 Result += Ivars[i]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +0000874 Result += "\", \"";
875 std::string StrEncoding;
876 Context->getObjcEncodingForType(Ivars[i]->getType(), StrEncoding);
877 Result += StrEncoding;
878 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000879 SynthesizeIvarOffsetComputation(IDecl, Ivars[i], Result);
880 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000881 }
882
883 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000884 }
885
886 // Build _objc_method_list for class's instance methods if needed
887 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
888 IDecl->getNumInstanceMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000889 true,
890 "", IDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000891
892 // Build _objc_method_list for class's class methods if needed
893 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000894 IDecl->getNumClassMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000895 false,
896 "", IDecl->getName(), Result);
897
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000898 // Protocols referenced in class declaration?
899 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
900 CDecl->getNumIntfRefProtocols(),
901 "CLASS",
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000902 CDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000903
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000904
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000905 // Declaration of class/meta-class metadata
906 /* struct _objc_class {
907 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000908 const char *super_class_name;
909 char *name;
910 long version;
911 long info;
912 long instance_size;
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000913 struct _objc_ivar_list *ivars;
914 struct _objc_method_list *methods;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000915 struct objc_cache *cache;
916 struct objc_protocol_list *protocols;
917 const char *ivar_layout;
918 struct _objc_class_ext *ext;
919 };
920 */
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000921 static bool objc_class = false;
922 if (!objc_class) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000923 Result += "\nstruct _objc_class {\n";
924 Result += "\tstruct _objc_class *isa;\n";
925 Result += "\tconst char *super_class_name;\n";
926 Result += "\tchar *name;\n";
927 Result += "\tlong version;\n";
928 Result += "\tlong info;\n";
929 Result += "\tlong instance_size;\n";
930 Result += "\tstruct _objc_ivar_list *ivars;\n";
931 Result += "\tstruct _objc_method_list *methods;\n";
932 Result += "\tstruct objc_cache *cache;\n";
933 Result += "\tstruct _objc_protocol_list *protocols;\n";
934 Result += "\tconst char *ivar_layout;\n";
935 Result += "\tstruct _objc_class_ext *ext;\n";
936 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000937 objc_class = true;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000938 }
939
940 // Meta-class metadata generation.
941 ObjcInterfaceDecl *RootClass = 0;
942 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
943 while (SuperClass) {
944 RootClass = SuperClass;
945 SuperClass = SuperClass->getSuperClass();
946 }
947 SuperClass = CDecl->getSuperClass();
948
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000949 Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
950 Result += CDecl->getName();
951 Result += " __attribute__ ((section (\"__OBJC, __meta_class\")))= "
952 "{\n\t(struct _objc_class *)\"";
953 Result += (RootClass ? RootClass->getName() : CDecl->getName());
954 Result += "\"";
955
956 if (SuperClass) {
957 Result += ", \"";
958 Result += SuperClass->getName();
959 Result += "\", \"";
960 Result += CDecl->getName();
961 Result += "\"";
962 }
963 else {
964 Result += ", 0, \"";
965 Result += CDecl->getName();
966 Result += "\"";
967 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000968 // TODO: 'ivars' field for root class is currently set to 0.
969 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000970 Result += ", 0,2, sizeof(struct _objc_class), 0";
971 if (CDecl->getNumClassMethods() > 0) {
972 Result += "\n\t, &_OBJC_CLASS_METHODS_";
973 Result += CDecl->getName();
974 Result += "\n";
975 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000976 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000977 Result += ", 0\n";
978 if (CDecl->getNumIntfRefProtocols() > 0) {
979 Result += "\t,0, &_OBJC_CLASS_PROTOCOLS_";
980 Result += CDecl->getName();
981 Result += ",0,0\n";
982 }
Fariborz Jahanian454cb012007-10-24 20:54:23 +0000983 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000984 Result += "\t,0,0,0,0\n";
985 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000986
987 // class metadata generation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000988 Result += "\nstatic struct _objc_class _OBJC_CLASS_";
989 Result += CDecl->getName();
990 Result += " __attribute__ ((section (\"__OBJC, __class\")))= "
991 "{\n\t&_OBJC_METACLASS_";
992 Result += CDecl->getName();
993 if (SuperClass) {
994 Result += ", \"";
995 Result += SuperClass->getName();
996 Result += "\", \"";
997 Result += CDecl->getName();
998 Result += "\"";
999 }
1000 else {
1001 Result += ", 0, \"";
1002 Result += CDecl->getName();
1003 Result += "\"";
1004 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001005 // 'info' field is initialized to CLS_CLASS(1) for class
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00001006 Result += ", 0,1";
1007 if (!ObjcSynthesizedStructs.count(CDecl))
1008 Result += ",0";
1009 else {
1010 // class has size. Must synthesize its size.
1011 Result += ",sizeof(struct _interface_";
1012 Result += CDecl->getName();
1013 Result += ")";
1014 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001015 if (NumIvars > 0) {
1016 Result += ", &_OBJC_INSTANCE_VARIABLES_";
1017 Result += CDecl->getName();
1018 Result += "\n\t";
1019 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001020 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001021 Result += ",0";
1022 if (IDecl->getNumInstanceMethods() > 0) {
1023 Result += ", &_OBJC_INSTANCE_METHODS_";
1024 Result += CDecl->getName();
1025 Result += ", 0\n\t";
1026 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001027 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001028 Result += ",0,0";
1029 if (CDecl->getNumIntfRefProtocols() > 0) {
1030 Result += ", &_OBJC_CLASS_PROTOCOLS_";
1031 Result += CDecl->getName();
1032 Result += ", 0,0\n";
1033 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001034 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001035 Result += ",0,0,0\n";
1036 Result += "};\n";
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001037}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001038
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001039void RewriteTest::WriteObjcMetaData(std::string &Result) {
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001040 int ClsDefCount = ClassImplementation.size();
1041 int CatDefCount = CategoryImplementation.size();
1042 if (ClsDefCount == 0 && CatDefCount == 0)
1043 return;
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001044
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001045 // TODO: This is temporary until we decide how to access objc types in a
1046 // c program
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001047 Result += "#include <Objc/objc.h>\n";
1048 // This is needed for use of offsetof
1049 Result += "#include <stddef.h>\n";
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001050
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001051 // For each implemented class, write out all its meta data.
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001052 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001053 RewriteObjcClassMetaData(ClassImplementation[i], Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001054
1055 // For each implemented category, write out all its meta data.
1056 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001057 RewriteObjcCategoryImplDecl(CategoryImplementation[i], Result);
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001058
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001059 // Write objc_symtab metadata
1060 /*
1061 struct _objc_symtab
1062 {
1063 long sel_ref_cnt;
1064 SEL *refs;
1065 short cls_def_cnt;
1066 short cat_def_cnt;
1067 void *defs[cls_def_cnt + cat_def_cnt];
1068 };
1069 */
1070
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001071 Result += "\nstruct _objc_symtab {\n";
1072 Result += "\tlong sel_ref_cnt;\n";
1073 Result += "\tSEL *refs;\n";
1074 Result += "\tshort cls_def_cnt;\n";
1075 Result += "\tshort cat_def_cnt;\n";
1076 Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
1077 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001078
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001079 Result += "static struct _objc_symtab "
1080 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n";
1081 Result += "\t0, 0, " + utostr(ClsDefCount)
1082 + ", " + utostr(CatDefCount) + "\n";
1083 for (int i = 0; i < ClsDefCount; i++) {
1084 Result += "\t,&_OBJC_CLASS_";
1085 Result += ClassImplementation[i]->getName();
1086 Result += "\n";
1087 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001088
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001089 for (int i = 0; i < CatDefCount; i++) {
1090 Result += "\t,&_OBJC_CATEGORY_";
1091 Result += CategoryImplementation[i]->getClassInterface()->getName();
1092 Result += "_";
1093 Result += CategoryImplementation[i]->getName();
1094 Result += "\n";
1095 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001096
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001097 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001098
1099 // Write objc_module metadata
1100
1101 /*
1102 struct _objc_module {
1103 long version;
1104 long size;
1105 const char *name;
1106 struct _objc_symtab *symtab;
1107 }
1108 */
1109
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001110 Result += "\nstruct _objc_module {\n";
1111 Result += "\tlong version;\n";
1112 Result += "\tlong size;\n";
1113 Result += "\tconst char *name;\n";
1114 Result += "\tstruct _objc_symtab *symtab;\n";
1115 Result += "};\n\n";
1116 Result += "static struct _objc_module "
1117 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001118 Result += "\t" + utostr(OBJC_ABI_VERSION) +
1119 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001120 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001121}
Chris Lattner311ff022007-10-16 22:36:42 +00001122