blob: a7f1c209b3103b1d55ba0f91de70255382698e31 [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
Steve Naroffbeaf2992007-11-03 11:27:19 +000042 // ObjC string constant support.
43 FileVarDecl *ConstantStringClassReference;
44 RecordDecl *NSStringRecord;
Steve Naroffab972d32007-11-04 22:37:50 +000045
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000046 static const int OBJC_ABI_VERSION =7 ;
Chris Lattner77cd2a02007-10-11 00:43:27 +000047 public:
Chris Lattner01c57482007-10-17 22:35:30 +000048 void Initialize(ASTContext &context, unsigned mainFileID) {
49 Context = &context;
50 SM = &Context->SourceMgr;
Chris Lattner8a12c272007-10-11 18:38:32 +000051 MainFileID = mainFileID;
Steve Naroffebf2b562007-10-23 23:50:29 +000052 MsgSendFunctionDecl = 0;
Steve Naroffc0006092007-10-24 01:09:48 +000053 GetClassFunctionDecl = 0;
Steve Naroff934f2762007-10-24 22:48:43 +000054 SelGetUidFunctionDecl = 0;
Steve Naroffbeaf2992007-11-03 11:27:19 +000055 ConstantStringClassReference = 0;
56 NSStringRecord = 0;
Chris Lattner01c57482007-10-17 22:35:30 +000057 Rewrite.setSourceMgr(Context->SourceMgr);
Steve Naroffe3abbf52007-11-05 14:55:35 +000058 // declaring objc_selector outside the parameter list removes a silly
59 // scope related warning...
Steve Naroff21867b12007-11-07 18:43:40 +000060 const char *s = "struct objc_selector; struct objc_class;\n"
Steve Naroffe3abbf52007-11-05 14:55:35 +000061 "extern struct objc_object *objc_msgSend"
Steve Naroffab972d32007-11-04 22:37:50 +000062 "(struct objc_object *, struct objc_selector *, ...);\n"
63 "extern struct objc_object *objc_getClass"
Steve Naroff21867b12007-11-07 18:43:40 +000064 "(const char *);\n"
65 "extern void objc_exception_throw(struct objc_object *);\n"
66 "extern void objc_exception_try_enter(void *);\n"
67 "extern void objc_exception_try_exit(void *);\n"
68 "extern struct objc_object *objc_exception_extract(void *);\n"
69 "extern int objc_exception_match"
70 "(struct objc_class *, struct objc_object *, ...);\n";
71
Steve Naroffab972d32007-11-04 22:37:50 +000072 Rewrite.InsertText(SourceLocation::getFileLoc(mainFileID, 0),
73 s, strlen(s));
Chris Lattner77cd2a02007-10-11 00:43:27 +000074 }
Chris Lattner8a12c272007-10-11 18:38:32 +000075
Chris Lattnerf04da132007-10-24 17:06:59 +000076 // Top Level Driver code.
77 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner2c64b7b2007-10-16 21:07:07 +000078 void HandleDeclInMainFile(Decl *D);
Chris Lattnerf04da132007-10-24 17:06:59 +000079 ~RewriteTest();
80
81 // Syntactic Rewriting.
Steve Naroffab972d32007-11-04 22:37:50 +000082 void RewritePrologue(SourceLocation Loc);
Chris Lattner2c64b7b2007-10-16 21:07:07 +000083 void RewriteInclude(SourceLocation Loc);
Chris Lattnerf04da132007-10-24 17:06:59 +000084 void RewriteTabs();
85 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Steve Naroffbef11852007-10-26 20:53:56 +000086 void RewriteInterfaceDecl(ObjcInterfaceDecl *Dcl);
Steve Naroff423cb562007-10-30 13:30:57 +000087 void RewriteCategoryDecl(ObjcCategoryDecl *Dcl);
Steve Naroff752d6ef2007-10-30 16:42:30 +000088 void RewriteProtocolDecl(ObjcProtocolDecl *Dcl);
Steve Naroff423cb562007-10-30 13:30:57 +000089 void RewriteMethods(int nMethods, ObjcMethodDecl **Methods);
Fariborz Jahanian957cf652007-11-07 00:09:37 +000090 void RewriteProperties(int nProperties, ObjcPropertyDecl **Properties);
Steve Naroff09b266e2007-10-30 23:14:51 +000091 void RewriteFunctionDecl(FunctionDecl *FD);
Steve Naroffd5255f52007-11-01 13:24:47 +000092 void RewriteObjcQualifiedInterfaceTypes(
93 const FunctionTypeProto *proto, FunctionDecl *FD);
94 bool needToScanForQualifiers(QualType T);
Chris Lattner311ff022007-10-16 22:36:42 +000095
Chris Lattnerf04da132007-10-24 17:06:59 +000096 // Expression Rewriting.
Chris Lattnere64b7772007-10-24 16:57:36 +000097 Stmt *RewriteFunctionBody(Stmt *S);
98 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
Steve Naroffb42f8412007-11-05 14:50:49 +000099 Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
Chris Lattnere64b7772007-10-24 16:57:36 +0000100 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroffbeaf2992007-11-03 11:27:19 +0000101 Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000102 Stmt *RewriteObjcTryStmt(ObjcAtTryStmt *S);
103 Stmt *RewriteObjcCatchStmt(ObjcAtCatchStmt *S);
104 Stmt *RewriteObjcFinallyStmt(ObjcAtFinallyStmt *S);
Steve Naroff2bd03922007-11-07 15:32:26 +0000105 Stmt *RewriteObjcThrowStmt(ObjcAtThrowStmt *S);
Steve Naroff934f2762007-10-24 22:48:43 +0000106 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
107 Expr **args, unsigned nargs);
Steve Naroff09b266e2007-10-30 23:14:51 +0000108 void SynthMsgSendFunctionDecl();
109 void SynthGetClassFunctionDecl();
110
Chris Lattnerf04da132007-10-24 17:06:59 +0000111 // Metadata emission.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000112 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
113 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000114
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000115 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl,
116 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000117
118 void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
119 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000120 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000121 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +0000122 const char *ClassName,
123 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000124
125 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
126 int NumProtocols,
127 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000128 const char *ClassName,
129 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000130 void SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
131 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000132 void SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
133 ObjcIvarDecl *ivar,
134 std::string &Result);
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000135 void WriteObjcMetaData(std::string &Result);
Chris Lattner77cd2a02007-10-11 00:43:27 +0000136 };
137}
138
Chris Lattner8a12c272007-10-11 18:38:32 +0000139ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattner77cd2a02007-10-11 00:43:27 +0000140
Chris Lattnerf04da132007-10-24 17:06:59 +0000141//===----------------------------------------------------------------------===//
142// Top Level Driver Code
143//===----------------------------------------------------------------------===//
144
Chris Lattner8a12c272007-10-11 18:38:32 +0000145void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000146 // Two cases: either the decl could be in the main file, or it could be in a
147 // #included file. If the former, rewrite it now. If the later, check to see
148 // if we rewrote the #include/#import.
149 SourceLocation Loc = D->getLocation();
150 Loc = SM->getLogicalLoc(Loc);
151
152 // If this is for a builtin, ignore it.
153 if (Loc.isInvalid()) return;
154
Steve Naroffebf2b562007-10-23 23:50:29 +0000155 // Look for built-in declarations that we need to refer during the rewrite.
156 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroff09b266e2007-10-30 23:14:51 +0000157 RewriteFunctionDecl(FD);
Steve Naroffbeaf2992007-11-03 11:27:19 +0000158 } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
159 // declared in <Foundation/NSString.h>
160 if (strcmp(FVD->getName(), "_NSConstantStringClassReference") == 0) {
161 ConstantStringClassReference = FVD;
162 return;
163 }
Steve Naroffbef11852007-10-26 20:53:56 +0000164 } else if (ObjcInterfaceDecl *MD = dyn_cast<ObjcInterfaceDecl>(D)) {
165 RewriteInterfaceDecl(MD);
Steve Naroff423cb562007-10-30 13:30:57 +0000166 } else if (ObjcCategoryDecl *CD = dyn_cast<ObjcCategoryDecl>(D)) {
167 RewriteCategoryDecl(CD);
Steve Naroff752d6ef2007-10-30 16:42:30 +0000168 } else if (ObjcProtocolDecl *PD = dyn_cast<ObjcProtocolDecl>(D)) {
169 RewriteProtocolDecl(PD);
Steve Naroffebf2b562007-10-23 23:50:29 +0000170 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000171 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000172 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
173 return HandleDeclInMainFile(D);
174
Chris Lattnerf04da132007-10-24 17:06:59 +0000175 // Otherwise, see if there is a #import in the main file that should be
176 // rewritten.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000177 RewriteInclude(Loc);
178}
179
Chris Lattnerf04da132007-10-24 17:06:59 +0000180/// HandleDeclInMainFile - This is called for each top-level decl defined in the
181/// main file of the input.
182void RewriteTest::HandleDeclInMainFile(Decl *D) {
183 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
184 if (Stmt *Body = FD->getBody())
185 FD->setBody(RewriteFunctionBody(Body));
186
187 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
188 ClassImplementation.push_back(CI);
189 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
190 CategoryImplementation.push_back(CI);
191 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
192 RewriteForwardClassDecl(CD);
193 // Nothing yet.
194}
195
196RewriteTest::~RewriteTest() {
197 // Get the top-level buffer that this corresponds to.
Chris Lattner74a0c772007-11-08 04:27:23 +0000198
199 // Rewrite tabs if we care.
200 //RewriteTabs();
Chris Lattnerf04da132007-10-24 17:06:59 +0000201
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000202 // Rewrite Objective-c meta data*
203 std::string ResultStr;
204 WriteObjcMetaData(ResultStr);
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000205
Chris Lattnerf04da132007-10-24 17:06:59 +0000206 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
207 // we are done.
208 if (const RewriteBuffer *RewriteBuf =
209 Rewrite.getRewriteBufferFor(MainFileID)) {
Steve Naroffbeaf2992007-11-03 11:27:19 +0000210 //printf("Changed:\n");
Chris Lattnerf04da132007-10-24 17:06:59 +0000211 std::string S(RewriteBuf->begin(), RewriteBuf->end());
212 printf("%s\n", S.c_str());
213 } else {
214 printf("No changes\n");
215 }
Fariborz Jahanian4402d812007-11-07 18:40:28 +0000216 // Emit metadata.
217 printf("%s", ResultStr.c_str());
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000218}
219
Chris Lattnerf04da132007-10-24 17:06:59 +0000220//===----------------------------------------------------------------------===//
221// Syntactic (non-AST) Rewriting Code
222//===----------------------------------------------------------------------===//
223
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000224void RewriteTest::RewriteInclude(SourceLocation Loc) {
225 // Rip up the #include stack to the main file.
226 SourceLocation IncLoc = Loc, NextLoc = Loc;
227 do {
228 IncLoc = Loc;
229 Loc = SM->getLogicalLoc(NextLoc);
230 NextLoc = SM->getIncludeLoc(Loc);
231 } while (!NextLoc.isInvalid());
232
233 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
234 // IncLoc indicates the header that was included if it is useful.
235 IncLoc = SM->getLogicalLoc(IncLoc);
236 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
237 Loc == LastIncLoc)
238 return;
239 LastIncLoc = Loc;
240
241 unsigned IncCol = SM->getColumnNumber(Loc);
242 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
243
244 // Replace the #import with #include.
245 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
246}
247
Chris Lattnerf04da132007-10-24 17:06:59 +0000248void RewriteTest::RewriteTabs() {
249 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
250 const char *MainBufStart = MainBuf.first;
251 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000252
Chris Lattnerf04da132007-10-24 17:06:59 +0000253 // Loop over the whole file, looking for tabs.
254 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
255 if (*BufPtr != '\t')
256 continue;
257
258 // Okay, we found a tab. This tab will turn into at least one character,
259 // but it depends on which 'virtual column' it is in. Compute that now.
260 unsigned VCol = 0;
261 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
262 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
263 ++VCol;
264
265 // Okay, now that we know the virtual column, we know how many spaces to
266 // insert. We assume 8-character tab-stops.
267 unsigned Spaces = 8-(VCol & 7);
268
269 // Get the location of the tab.
270 SourceLocation TabLoc =
271 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
272
273 // Rewrite the single tab character into a sequence of spaces.
274 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
275 }
Chris Lattner8a12c272007-10-11 18:38:32 +0000276}
277
278
Chris Lattnerf04da132007-10-24 17:06:59 +0000279void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
280 int numDecls = ClassDecl->getNumForwardDecls();
281 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
282
283 // Get the start location and compute the semi location.
284 SourceLocation startLoc = ClassDecl->getLocation();
285 const char *startBuf = SM->getCharacterData(startLoc);
286 const char *semiPtr = strchr(startBuf, ';');
287
288 // Translate to typedef's that forward reference structs with the same name
289 // as the class. As a convenience, we include the original declaration
290 // as a comment.
291 std::string typedefString;
292 typedefString += "// ";
Steve Naroff934f2762007-10-24 22:48:43 +0000293 typedefString.append(startBuf, semiPtr-startBuf+1);
294 typedefString += "\n";
295 for (int i = 0; i < numDecls; i++) {
296 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
Steve Naroff8749be52007-10-31 22:11:35 +0000297 if (ObjcForwardDecls.count(ForwardDecl))
298 continue;
Steve Naroff352336b2007-11-05 14:36:37 +0000299 typedefString += "typedef struct objc_object ";
Steve Naroff934f2762007-10-24 22:48:43 +0000300 typedefString += ForwardDecl->getName();
301 typedefString += ";\n";
Steve Naroff8749be52007-10-31 22:11:35 +0000302
303 // Mark this typedef as having been generated.
304 if (!ObjcForwardDecls.insert(ForwardDecl))
Fariborz Jahanianaff56d02007-10-31 22:57:04 +0000305 assert(false && "typedef already output");
Steve Naroff934f2762007-10-24 22:48:43 +0000306 }
307
308 // Replace the @class with typedefs corresponding to the classes.
309 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
310 typedefString.c_str(), typedefString.size());
Chris Lattnerf04da132007-10-24 17:06:59 +0000311}
312
Steve Naroff423cb562007-10-30 13:30:57 +0000313void RewriteTest::RewriteMethods(int nMethods, ObjcMethodDecl **Methods) {
314 for (int i = 0; i < nMethods; i++) {
315 ObjcMethodDecl *Method = Methods[i];
316 SourceLocation Loc = Method->getLocStart();
317
318 Rewrite.ReplaceText(Loc, 0, "// ", 3);
319
320 // FIXME: handle methods that are declared across multiple lines.
321 }
322}
323
Fariborz Jahanian957cf652007-11-07 00:09:37 +0000324void RewriteTest::RewriteProperties(int nProperties, ObjcPropertyDecl **Properties)
325{
326 for (int i = 0; i < nProperties; i++) {
327 ObjcPropertyDecl *Property = Properties[i];
328 SourceLocation Loc = Property->getLocation();
329
330 Rewrite.ReplaceText(Loc, 0, "// ", 3);
331
332 // FIXME: handle properties that are declared across multiple lines.
333 }
334}
335
Steve Naroff423cb562007-10-30 13:30:57 +0000336void RewriteTest::RewriteCategoryDecl(ObjcCategoryDecl *CatDecl) {
337 SourceLocation LocStart = CatDecl->getLocStart();
338
339 // FIXME: handle category headers that are declared across multiple lines.
340 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
341
342 RewriteMethods(CatDecl->getNumInstanceMethods(),
343 CatDecl->getInstanceMethods());
344 RewriteMethods(CatDecl->getNumClassMethods(),
345 CatDecl->getClassMethods());
346 // Lastly, comment out the @end.
347 Rewrite.ReplaceText(CatDecl->getAtEndLoc(), 0, "// ", 3);
348}
349
Steve Naroff752d6ef2007-10-30 16:42:30 +0000350void RewriteTest::RewriteProtocolDecl(ObjcProtocolDecl *PDecl) {
351 SourceLocation LocStart = PDecl->getLocStart();
352
353 // FIXME: handle protocol headers that are declared across multiple lines.
354 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
355
356 RewriteMethods(PDecl->getNumInstanceMethods(),
357 PDecl->getInstanceMethods());
358 RewriteMethods(PDecl->getNumClassMethods(),
359 PDecl->getClassMethods());
360 // Lastly, comment out the @end.
361 Rewrite.ReplaceText(PDecl->getAtEndLoc(), 0, "// ", 3);
362}
363
Steve Naroffbef11852007-10-26 20:53:56 +0000364void RewriteTest::RewriteInterfaceDecl(ObjcInterfaceDecl *ClassDecl) {
Steve Narofff908a872007-10-30 02:23:23 +0000365
366 SourceLocation LocStart = ClassDecl->getLocStart();
367 SourceLocation LocEnd = ClassDecl->getLocEnd();
368
369 const char *startBuf = SM->getCharacterData(LocStart);
370 const char *endBuf = SM->getCharacterData(LocEnd);
371
Steve Naroff2feac5e2007-10-30 03:43:13 +0000372 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM);
Steve Narofff908a872007-10-30 02:23:23 +0000373
374 std::string ResultStr;
Steve Naroff6c6a2db2007-11-01 03:35:41 +0000375 if (!ObjcForwardDecls.count(ClassDecl)) {
376 // we haven't seen a forward decl - generate a typedef.
Steve Naroff352336b2007-11-05 14:36:37 +0000377 ResultStr += "typedef struct objc_object ";
Steve Naroff6c6a2db2007-11-01 03:35:41 +0000378 ResultStr += ClassDecl->getName();
379 ResultStr += ";";
380
381 // Mark this typedef as having been generated.
382 ObjcForwardDecls.insert(ClassDecl);
383 }
Steve Narofff908a872007-10-30 02:23:23 +0000384 SynthesizeObjcInternalStruct(ClassDecl, ResultStr);
385
Steve Naroff2feac5e2007-10-30 03:43:13 +0000386 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
Steve Narofff908a872007-10-30 02:23:23 +0000387 ResultStr.c_str(), ResultStr.size());
Fariborz Jahanian957cf652007-11-07 00:09:37 +0000388 RewriteProperties(ClassDecl->getNumPropertyDecl(),
389 ClassDecl->getPropertyDecl());
Steve Naroff423cb562007-10-30 13:30:57 +0000390 RewriteMethods(ClassDecl->getNumInstanceMethods(),
391 ClassDecl->getInstanceMethods());
392 RewriteMethods(ClassDecl->getNumClassMethods(),
393 ClassDecl->getClassMethods());
Steve Naroffbef11852007-10-26 20:53:56 +0000394
Steve Naroff2feac5e2007-10-30 03:43:13 +0000395 // Lastly, comment out the @end.
396 Rewrite.ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3);
Steve Naroffbef11852007-10-26 20:53:56 +0000397}
398
Chris Lattnerf04da132007-10-24 17:06:59 +0000399//===----------------------------------------------------------------------===//
400// Function Body / Expression rewriting
401//===----------------------------------------------------------------------===//
402
Chris Lattnere64b7772007-10-24 16:57:36 +0000403Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner311ff022007-10-16 22:36:42 +0000404 // Otherwise, just rewrite all children.
405 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
406 CI != E; ++CI)
Steve Naroff75730982007-11-07 04:08:17 +0000407 if (*CI) {
408 Stmt *newStmt = RewriteFunctionBody(*CI);
409 if (newStmt)
410 *CI = newStmt;
411 }
Steve Naroffebf2b562007-10-23 23:50:29 +0000412
413 // Handle specific things.
414 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
415 return RewriteAtEncode(AtEncode);
Steve Naroffb42f8412007-11-05 14:50:49 +0000416
417 if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
418 return RewriteAtSelector(AtSelector);
Steve Naroffbeaf2992007-11-03 11:27:19 +0000419
420 if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
421 return RewriteObjCStringLiteral(AtString);
Steve Naroffebf2b562007-10-23 23:50:29 +0000422
Steve Naroff934f2762007-10-24 22:48:43 +0000423 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
424 // Before we rewrite it, put the original message expression in a comment.
425 SourceLocation startLoc = MessExpr->getLocStart();
426 SourceLocation endLoc = MessExpr->getLocEnd();
427
428 const char *startBuf = SM->getCharacterData(startLoc);
429 const char *endBuf = SM->getCharacterData(endLoc);
430
431 std::string messString;
432 messString += "// ";
433 messString.append(startBuf, endBuf-startBuf+1);
434 messString += "\n";
Steve Naroffbef11852007-10-26 20:53:56 +0000435
Steve Naroff934f2762007-10-24 22:48:43 +0000436 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
437 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
438 // Tried this, but it didn't work either...
Steve Naroff752d6ef2007-10-30 16:42:30 +0000439 // Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffebf2b562007-10-23 23:50:29 +0000440 return RewriteMessageExpr(MessExpr);
Steve Naroff934f2762007-10-24 22:48:43 +0000441 }
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000442
443 if (ObjcAtTryStmt *StmtTry = dyn_cast<ObjcAtTryStmt>(S))
444 return RewriteObjcTryStmt(StmtTry);
Steve Naroff2bd03922007-11-07 15:32:26 +0000445
446 if (ObjcAtThrowStmt *StmtThrow = dyn_cast<ObjcAtThrowStmt>(S))
447 return RewriteObjcThrowStmt(StmtThrow);
448
Chris Lattnere64b7772007-10-24 16:57:36 +0000449 // Return this stmt unmodified.
450 return S;
Chris Lattner311ff022007-10-16 22:36:42 +0000451}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000452
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000453Stmt *RewriteTest::RewriteObjcTryStmt(ObjcAtTryStmt *S) {
Steve Naroff75730982007-11-07 04:08:17 +0000454 // Get the start location and compute the semi location.
455 SourceLocation startLoc = S->getLocStart();
456 const char *startBuf = SM->getCharacterData(startLoc);
457
458 assert((*startBuf == '@') && "bogus @try location");
459
460 std::string buf;
461 // declare a new scope with two variables, _stack and _rethrow.
462 buf = "/* @try scope begin */ { struct _objc_exception_data {\n";
463 buf += "int buf[18/*32-bit i386*/];\n";
464 buf += "char *pointers[4];} _stack;\n";
465 buf += "id volatile _rethrow = 0;\n";
466 buf += "objc_exception_try_enter(&_stack);\n";
Steve Naroff21867b12007-11-07 18:43:40 +0000467 buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
Steve Naroff75730982007-11-07 04:08:17 +0000468
469 Rewrite.ReplaceText(startLoc, 4, buf.c_str(), buf.size());
470
471 startLoc = S->getTryBody()->getLocEnd();
472 startBuf = SM->getCharacterData(startLoc);
473
474 assert((*startBuf == '}') && "bogus @try block");
475
476 SourceLocation lastCurlyLoc = startLoc;
477
478 startLoc = startLoc.getFileLocWithOffset(1);
479 buf = " /* @catch begin */ else {\n";
480 buf += " id _caught = objc_exception_extract(&_stack);\n";
481 buf += " objc_exception_try_enter (&_stack);\n";
Steve Naroff21867b12007-11-07 18:43:40 +0000482 buf += " if (_setjmp(_stack.buf))\n";
Steve Naroff75730982007-11-07 04:08:17 +0000483 buf += " _rethrow = objc_exception_extract(&_stack);\n";
484 buf += " else { /* @catch continue */";
485
486 Rewrite.ReplaceText(startLoc, 0, buf.c_str(), buf.size());
487
488 bool sawIdTypedCatch = false;
489 Stmt *lastCatchBody = 0;
490 ObjcAtCatchStmt *catchList = S->getCatchStmts();
491 while (catchList) {
492 Stmt *catchStmt = catchList->getCatchParamStmt();
493
494 if (catchList == S->getCatchStmts())
495 buf = "if ("; // we are generating code for the first catch clause
496 else
497 buf = "else if (";
498 startLoc = catchList->getLocStart();
499 startBuf = SM->getCharacterData(startLoc);
500
501 assert((*startBuf == '@') && "bogus @catch location");
502
503 const char *lParenLoc = strchr(startBuf, '(');
504
505 if (DeclStmt *declStmt = dyn_cast<DeclStmt>(catchStmt)) {
506 QualType t = dyn_cast<ValueDecl>(declStmt->getDecl())->getType();
507 if (t == Context->getObjcIdType()) {
508 buf += "1) { ";
509 Rewrite.ReplaceText(startLoc, lParenLoc-startBuf+1,
510 buf.c_str(), buf.size());
511 sawIdTypedCatch = true;
512 } else if (const PointerType *pType = t->getAsPointerType()) {
513 ObjcInterfaceType *cls; // Should be a pointer to a class.
514
515 cls = dyn_cast<ObjcInterfaceType>(pType->getPointeeType().getTypePtr());
516 if (cls) {
Steve Naroff21867b12007-11-07 18:43:40 +0000517 buf += "objc_exception_match((struct objc_class *)objc_getClass(\"";
Steve Naroff75730982007-11-07 04:08:17 +0000518 buf += cls->getDecl()->getName();
Steve Naroff21867b12007-11-07 18:43:40 +0000519 buf += "\"), (struct objc_object *)_caught)) { ";
Steve Naroff75730982007-11-07 04:08:17 +0000520 Rewrite.ReplaceText(startLoc, lParenLoc-startBuf+1,
521 buf.c_str(), buf.size());
522 }
523 }
524 // Now rewrite the body...
525 lastCatchBody = catchList->getCatchBody();
526 SourceLocation rParenLoc = catchList->getRParenLoc();
527 SourceLocation bodyLoc = lastCatchBody->getLocStart();
528 const char *bodyBuf = SM->getCharacterData(bodyLoc);
529 const char *rParenBuf = SM->getCharacterData(rParenLoc);
530 assert((*rParenBuf == ')') && "bogus @catch paren location");
531 assert((*bodyBuf == '{') && "bogus @catch body location");
532
533 buf = " = _caught;";
534 // Here we replace ") {" with "= _caught;" (which initializes and
535 // declares the @catch parameter).
536 Rewrite.ReplaceText(rParenLoc, bodyBuf-rParenBuf+1,
537 buf.c_str(), buf.size());
Steve Naroff2bd03922007-11-07 15:32:26 +0000538 } else if (!isa<NullStmt>(catchStmt)) {
Steve Naroff75730982007-11-07 04:08:17 +0000539 assert(false && "@catch rewrite bug");
Steve Naroff2bd03922007-11-07 15:32:26 +0000540 }
Steve Naroff75730982007-11-07 04:08:17 +0000541 catchList = catchList->getNextCatchStmt();
542 }
543 // Complete the catch list...
544 if (lastCatchBody) {
545 SourceLocation bodyLoc = lastCatchBody->getLocEnd();
546 const char *bodyBuf = SM->getCharacterData(bodyLoc);
547 assert((*bodyBuf == '}') && "bogus @catch body location");
548 bodyLoc = bodyLoc.getFileLocWithOffset(1);
549 buf = " } } /* @catch end */\n";
550
551 Rewrite.ReplaceText(bodyLoc, 0, buf.c_str(), buf.size());
552
553 // Set lastCurlyLoc
554 lastCurlyLoc = lastCatchBody->getLocEnd();
555 }
556 if (ObjcAtFinallyStmt *finalStmt = S->getFinallyStmt()) {
557 startLoc = finalStmt->getLocStart();
558 startBuf = SM->getCharacterData(startLoc);
559 assert((*startBuf == '@') && "bogus @finally start");
560
561 buf = "/* @finally */";
562 Rewrite.ReplaceText(startLoc, 8, buf.c_str(), buf.size());
563
564 Stmt *body = finalStmt->getFinallyBody();
565 SourceLocation startLoc = body->getLocStart();
566 SourceLocation endLoc = body->getLocEnd();
567 const char *startBuf = SM->getCharacterData(startLoc);
568 const char *endBuf = SM->getCharacterData(endLoc);
569 assert((*startBuf == '{') && "bogus @finally body location");
570 assert((*endBuf == '}') && "bogus @finally body location");
571
572 startLoc = startLoc.getFileLocWithOffset(1);
573 buf = " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
574 Rewrite.ReplaceText(startLoc, 0, buf.c_str(), buf.size());
575 endLoc = endLoc.getFileLocWithOffset(-1);
576 buf = " if (_rethrow) objc_exception_throw(_rethrow);\n";
577 Rewrite.ReplaceText(endLoc, 0, buf.c_str(), buf.size());
578
579 // Set lastCurlyLoc
580 lastCurlyLoc = body->getLocEnd();
581 }
582 // Now emit the final closing curly brace...
583 lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1);
584 buf = " } /* @try scope end */\n";
585 Rewrite.ReplaceText(lastCurlyLoc, 0, buf.c_str(), buf.size());
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000586 return 0;
587}
588
589Stmt *RewriteTest::RewriteObjcCatchStmt(ObjcAtCatchStmt *S) {
590 return 0;
591}
592
593Stmt *RewriteTest::RewriteObjcFinallyStmt(ObjcAtFinallyStmt *S) {
594 return 0;
595}
596
Steve Naroff2bd03922007-11-07 15:32:26 +0000597// This can't be done with Rewrite.ReplaceStmt(S, ThrowExpr), since
598// the throw expression is typically a message expression that's already
599// been rewritten! (which implies the SourceLocation's are invalid).
600Stmt *RewriteTest::RewriteObjcThrowStmt(ObjcAtThrowStmt *S) {
601 // Get the start location and compute the semi location.
602 SourceLocation startLoc = S->getLocStart();
603 const char *startBuf = SM->getCharacterData(startLoc);
604
605 assert((*startBuf == '@') && "bogus @throw location");
606
607 std::string buf;
608 /* void objc_exception_throw(id) __attribute__((noreturn)); */
609 buf = "objc_exception_throw(";
610 Rewrite.ReplaceText(startLoc, 6, buf.c_str(), buf.size());
611 const char *semiBuf = strchr(startBuf, ';');
612 assert((*semiBuf == ';') && "@throw: can't find ';'");
613 SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf);
614 buf = ");";
615 Rewrite.ReplaceText(semiLoc, 1, buf.c_str(), buf.size());
616 return 0;
617}
Fariborz Jahanian909f02a2007-11-05 17:47:33 +0000618
Chris Lattnere64b7772007-10-24 16:57:36 +0000619Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattner01c57482007-10-17 22:35:30 +0000620 // Create a new string expression.
621 QualType StrType = Context->getPointerType(Context->CharTy);
Anders Carlsson85f9bce2007-10-29 05:01:08 +0000622 std::string StrEncoding;
623 Context->getObjcEncodingForType(Exp->getEncodedType(), StrEncoding);
624 Expr *Replacement = new StringLiteral(StrEncoding.c_str(),
625 StrEncoding.length(), false, StrType,
Chris Lattner01c57482007-10-17 22:35:30 +0000626 SourceLocation(), SourceLocation());
627 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattnere64b7772007-10-24 16:57:36 +0000628 delete Exp;
629 return Replacement;
Chris Lattner311ff022007-10-16 22:36:42 +0000630}
631
Steve Naroffb42f8412007-11-05 14:50:49 +0000632Stmt *RewriteTest::RewriteAtSelector(ObjCSelectorExpr *Exp) {
633 assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
634 // Create a call to sel_registerName("selName").
635 llvm::SmallVector<Expr*, 8> SelExprs;
636 QualType argType = Context->getPointerType(Context->CharTy);
637 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
638 Exp->getSelector().getName().size(),
639 false, argType, SourceLocation(),
640 SourceLocation()));
641 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
642 &SelExprs[0], SelExprs.size());
643 Rewrite.ReplaceStmt(Exp, SelExp);
644 delete Exp;
645 return SelExp;
646}
647
Steve Naroff934f2762007-10-24 22:48:43 +0000648CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
649 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffebf2b562007-10-23 23:50:29 +0000650 // Get the type, we will need to reference it in a couple spots.
Steve Naroff934f2762007-10-24 22:48:43 +0000651 QualType msgSendType = FD->getType();
Steve Naroffebf2b562007-10-23 23:50:29 +0000652
653 // Create a reference to the objc_msgSend() declaration.
Steve Naroff934f2762007-10-24 22:48:43 +0000654 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffebf2b562007-10-23 23:50:29 +0000655
656 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerf04da132007-10-24 17:06:59 +0000657 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffebf2b562007-10-23 23:50:29 +0000658 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
659
660 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattnere64b7772007-10-24 16:57:36 +0000661
Steve Naroff934f2762007-10-24 22:48:43 +0000662 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
663}
664
Steve Naroffd5255f52007-11-01 13:24:47 +0000665static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
666 const char *&startRef, const char *&endRef) {
667 while (startBuf < endBuf) {
668 if (*startBuf == '<')
669 startRef = startBuf; // mark the start.
670 if (*startBuf == '>') {
671 assert((startRef && *startRef == '<') && "rewrite scanning error");
672 endRef = startBuf; // mark the end.
673 return true;
674 }
675 startBuf++;
676 }
677 return false;
678}
679
680bool RewriteTest::needToScanForQualifiers(QualType T) {
681 // FIXME: we don't currently represent "id <Protocol>" in the type system.
682 if (T == Context->getObjcIdType())
683 return true;
684
685 if (const PointerType *pType = T->getAsPointerType()) {
Steve Naroff9165ad32007-10-31 04:38:33 +0000686 Type *pointeeType = pType->getPointeeType().getTypePtr();
687 if (isa<ObjcQualifiedInterfaceType>(pointeeType))
688 return true; // we have "Class <Protocol> *".
689 }
Steve Naroffd5255f52007-11-01 13:24:47 +0000690 return false;
691}
692
693void RewriteTest::RewriteObjcQualifiedInterfaceTypes(
694 const FunctionTypeProto *proto, FunctionDecl *FD) {
695
696 if (needToScanForQualifiers(proto->getResultType())) {
697 // Since types are unique, we need to scan the buffer.
698 SourceLocation Loc = FD->getLocation();
699
700 const char *endBuf = SM->getCharacterData(Loc);
701 const char *startBuf = endBuf;
702 while (*startBuf != ';')
703 startBuf--; // scan backward (from the decl location) for return type.
704 const char *startRef = 0, *endRef = 0;
705 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
706 // Get the locations of the startRef, endRef.
707 SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf);
708 SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1);
709 // Comment out the protocol references.
710 Rewrite.ReplaceText(LessLoc, 0, "/*", 2);
711 Rewrite.ReplaceText(GreaterLoc, 0, "*/", 2);
Steve Naroff9165ad32007-10-31 04:38:33 +0000712 }
713 }
Steve Naroffd5255f52007-11-01 13:24:47 +0000714 // Now check arguments.
715 for (unsigned i = 0; i < proto->getNumArgs(); i++) {
716 if (needToScanForQualifiers(proto->getArgType(i))) {
717 // Since types are unique, we need to scan the buffer.
718 SourceLocation Loc = FD->getLocation();
719
720 const char *startBuf = SM->getCharacterData(Loc);
721 const char *endBuf = startBuf;
722 while (*endBuf != ';')
723 endBuf++; // scan forward (from the decl location) for argument types.
724 const char *startRef = 0, *endRef = 0;
725 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
726 // Get the locations of the startRef, endRef.
727 SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf);
728 SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1);
729 // Comment out the protocol references.
730 Rewrite.ReplaceText(LessLoc, 0, "/*", 2);
731 Rewrite.ReplaceText(GreaterLoc, 0, "*/", 2);
732 }
733 }
734 }
Steve Naroff9165ad32007-10-31 04:38:33 +0000735}
736
Steve Naroff09b266e2007-10-30 23:14:51 +0000737void RewriteTest::RewriteFunctionDecl(FunctionDecl *FD) {
738 // declared in <objc/objc.h>
Steve Naroffbeaf2992007-11-03 11:27:19 +0000739 if (strcmp(FD->getName(), "sel_registerName") == 0) {
Steve Naroff09b266e2007-10-30 23:14:51 +0000740 SelGetUidFunctionDecl = FD;
Steve Naroff9165ad32007-10-31 04:38:33 +0000741 return;
742 }
743 // Check for ObjC 'id' and class types that have been adorned with protocol
744 // information (id<p>, C<p>*). The protocol references need to be rewritten!
745 const FunctionType *funcType = FD->getType()->getAsFunctionType();
746 assert(funcType && "missing function type");
Steve Naroffd5255f52007-11-01 13:24:47 +0000747 if (const FunctionTypeProto *proto = dyn_cast<FunctionTypeProto>(funcType))
748 RewriteObjcQualifiedInterfaceTypes(proto, FD);
Steve Naroff09b266e2007-10-30 23:14:51 +0000749}
750
751// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
752void RewriteTest::SynthMsgSendFunctionDecl() {
753 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
754 llvm::SmallVector<QualType, 16> ArgTys;
755 QualType argT = Context->getObjcIdType();
756 assert(!argT.isNull() && "Can't find 'id' type");
757 ArgTys.push_back(argT);
758 argT = Context->getObjcSelType();
759 assert(!argT.isNull() && "Can't find 'SEL' type");
760 ArgTys.push_back(argT);
761 QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
762 &ArgTys[0], ArgTys.size(),
763 true /*isVariadic*/);
764 MsgSendFunctionDecl = new FunctionDecl(SourceLocation(),
765 msgSendIdent, msgSendType,
766 FunctionDecl::Extern, false, 0);
767}
768
769// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
770void RewriteTest::SynthGetClassFunctionDecl() {
771 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
772 llvm::SmallVector<QualType, 16> ArgTys;
773 ArgTys.push_back(Context->getPointerType(
774 Context->CharTy.getQualifiedType(QualType::Const)));
775 QualType getClassType = Context->getFunctionType(Context->getObjcIdType(),
776 &ArgTys[0], ArgTys.size(),
777 false /*isVariadic*/);
778 GetClassFunctionDecl = new FunctionDecl(SourceLocation(),
779 getClassIdent, getClassType,
780 FunctionDecl::Extern, false, 0);
781}
782
Steve Naroffbeaf2992007-11-03 11:27:19 +0000783Stmt *RewriteTest::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
784 assert(ConstantStringClassReference && "Can't find constant string reference");
785 llvm::SmallVector<Expr*, 4> InitExprs;
786
787 // Synthesize "(Class)&_NSConstantStringClassReference"
788 DeclRefExpr *ClsRef = new DeclRefExpr(ConstantStringClassReference,
789 ConstantStringClassReference->getType(),
790 SourceLocation());
791 QualType expType = Context->getPointerType(ClsRef->getType());
792 UnaryOperator *Unop = new UnaryOperator(ClsRef, UnaryOperator::AddrOf,
793 expType, SourceLocation());
794 CastExpr *cast = new CastExpr(Context->getObjcClassType(), Unop,
795 SourceLocation());
796 InitExprs.push_back(cast); // set the 'isa'.
797 InitExprs.push_back(Exp->getString()); // set "char *bytes".
798 unsigned IntSize = static_cast<unsigned>(
799 Context->getTypeSize(Context->IntTy, Exp->getLocStart()));
800 llvm::APInt IntVal(IntSize, Exp->getString()->getByteLength());
801 IntegerLiteral *len = new IntegerLiteral(IntVal, Context->IntTy,
802 Exp->getLocStart());
803 InitExprs.push_back(len); // set "int numBytes".
804
805 // struct NSConstantString
806 QualType CFConstantStrType = Context->getCFConstantStringType();
807 // (struct NSConstantString) { <exprs from above> }
808 InitListExpr *ILE = new InitListExpr(SourceLocation(),
809 &InitExprs[0], InitExprs.size(),
810 SourceLocation());
811 CompoundLiteralExpr *StrRep = new CompoundLiteralExpr(CFConstantStrType, ILE);
812 // struct NSConstantString *
813 expType = Context->getPointerType(StrRep->getType());
814 Unop = new UnaryOperator(StrRep, UnaryOperator::AddrOf, expType,
815 SourceLocation());
Steve Naroff352336b2007-11-05 14:36:37 +0000816 // cast to NSConstantString *
817 cast = new CastExpr(Exp->getType(), Unop, SourceLocation());
Steve Naroffbeaf2992007-11-03 11:27:19 +0000818 Rewrite.ReplaceStmt(Exp, cast);
819 delete Exp;
Steve Naroff352336b2007-11-05 14:36:37 +0000820 return cast;
Steve Naroffbeaf2992007-11-03 11:27:19 +0000821}
822
Steve Naroff934f2762007-10-24 22:48:43 +0000823Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
Steve Naroffbeaf2992007-11-03 11:27:19 +0000824 assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
Steve Naroff09b266e2007-10-30 23:14:51 +0000825 if (!MsgSendFunctionDecl)
826 SynthMsgSendFunctionDecl();
827 if (!GetClassFunctionDecl)
828 SynthGetClassFunctionDecl();
Steve Naroff934f2762007-10-24 22:48:43 +0000829
830 // Synthesize a call to objc_msgSend().
831 llvm::SmallVector<Expr*, 8> MsgExprs;
832 IdentifierInfo *clsName = Exp->getClassName();
833
834 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
835 if (clsName) { // class message.
836 llvm::SmallVector<Expr*, 8> ClsExprs;
837 QualType argType = Context->getPointerType(Context->CharTy);
838 ClsExprs.push_back(new StringLiteral(clsName->getName(),
839 clsName->getLength(),
840 false, argType, SourceLocation(),
841 SourceLocation()));
842 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
843 &ClsExprs[0], ClsExprs.size());
844 MsgExprs.push_back(Cls);
845 } else // instance message.
846 MsgExprs.push_back(Exp->getReceiver());
847
Steve Naroffbeaf2992007-11-03 11:27:19 +0000848 // Create a call to sel_registerName("selName"), it will be the 2nd argument.
Steve Naroff934f2762007-10-24 22:48:43 +0000849 llvm::SmallVector<Expr*, 8> SelExprs;
850 QualType argType = Context->getPointerType(Context->CharTy);
851 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
852 Exp->getSelector().getName().size(),
853 false, argType, SourceLocation(),
854 SourceLocation()));
855 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
856 &SelExprs[0], SelExprs.size());
857 MsgExprs.push_back(SelExp);
858
859 // Now push any user supplied arguments.
860 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
861 MsgExprs.push_back(Exp->getArg(i));
862 // We've transferred the ownership to MsgExprs. Null out the argument in
863 // the original expression, since we will delete it below.
864 Exp->setArg(i, 0);
865 }
Steve Naroffab972d32007-11-04 22:37:50 +0000866 // Generate the funky cast.
867 CastExpr *cast;
868 llvm::SmallVector<QualType, 8> ArgTypes;
869 QualType returnType;
870
871 // Push 'id' and 'SEL', the 2 implicit arguments.
872 ArgTypes.push_back(Context->getObjcIdType());
873 ArgTypes.push_back(Context->getObjcSelType());
874 if (ObjcMethodDecl *mDecl = Exp->getMethodDecl()) {
875 // Push any user argument types.
Steve Naroff352336b2007-11-05 14:36:37 +0000876 for (int i = 0; i < mDecl->getNumParams(); i++) {
877 QualType t = mDecl->getParamDecl(i)->getType();
878 if (t == Context->getObjcClassType())
879 t = Context->getObjcIdType(); // Convert "Class"->"id"
880 ArgTypes.push_back(t);
881 }
Steve Naroffab972d32007-11-04 22:37:50 +0000882 returnType = mDecl->getResultType();
883 } else {
884 returnType = Context->getObjcIdType();
885 }
886 // Get the type, we will need to reference it in a couple spots.
887 QualType msgSendType = MsgSendFunctionDecl->getType();
888
889 // Create a reference to the objc_msgSend() declaration.
890 DeclRefExpr *DRE = new DeclRefExpr(MsgSendFunctionDecl, msgSendType, SourceLocation());
891
892 // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
893 // If we don't do this cast, we get the following bizarre warning/note:
894 // xx.m:13: warning: function called through a non-compatible type
895 // xx.m:13: note: if this code is reached, the program will abort
896 cast = new CastExpr(Context->getPointerType(Context->VoidTy), DRE,
897 SourceLocation());
898
899 // Now do the "normal" pointer to function cast.
900 QualType castType = Context->getFunctionType(returnType,
901 &ArgTypes[0], ArgTypes.size(),
902 false/*FIXME:variadic*/);
903 castType = Context->getPointerType(castType);
904 cast = new CastExpr(castType, cast, SourceLocation());
905
906 // Don't forget the parens to enforce the proper binding.
907 ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), cast);
908
909 const FunctionType *FT = msgSendType->getAsFunctionType();
910 CallExpr *CE = new CallExpr(PE, &MsgExprs[0], MsgExprs.size(),
911 FT->getResultType(), SourceLocation());
Steve Naroff934f2762007-10-24 22:48:43 +0000912 // Now do the actual rewrite.
Steve Naroffab972d32007-11-04 22:37:50 +0000913 Rewrite.ReplaceStmt(Exp, CE);
Steve Naroff934f2762007-10-24 22:48:43 +0000914
Chris Lattnere64b7772007-10-24 16:57:36 +0000915 delete Exp;
Steve Naroffab972d32007-11-04 22:37:50 +0000916 return CE;
Steve Naroffebf2b562007-10-23 23:50:29 +0000917}
918
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000919/// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
920/// an objective-c class with ivars.
921void RewriteTest::SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
922 std::string &Result) {
923 assert(CDecl && "Class missing in SynthesizeObjcInternalStruct");
924 assert(CDecl->getName() && "Name missing in SynthesizeObjcInternalStruct");
Fariborz Jahanian212b7682007-10-31 23:08:24 +0000925 // Do not synthesize more than once.
926 if (ObjcSynthesizedStructs.count(CDecl))
927 return;
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000928 ObjcInterfaceDecl *RCDecl = CDecl->getSuperClass();
929 if (RCDecl && !ObjcSynthesizedStructs.count(RCDecl)) {
930 // Do it for the root
931 SynthesizeObjcInternalStruct(RCDecl, Result);
932 }
933
934 int NumIvars = CDecl->getIntfDeclNumIvars();
Fariborz Jahanianaff56d02007-10-31 22:57:04 +0000935 // If no ivars and no root or if its root, directly or indirectly,
Fariborz Jahanianf1de0ca2007-10-31 23:53:01 +0000936 // have no ivars (thus not synthesized) then no need to synthesize this class.
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000937 if (NumIvars <= 0 && (!RCDecl || !ObjcSynthesizedStructs.count(RCDecl)))
938 return;
939
Steve Naroff04960052007-11-01 17:12:31 +0000940 Result += "\nstruct ";
941 Result += CDecl->getName();
942 if (RCDecl && ObjcSynthesizedStructs.count(RCDecl)) {
943 Result += " {\n struct ";
944 Result += RCDecl->getName();
945 Result += " _";
946 Result += RCDecl->getName();
947 Result += ";\n";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000948 }
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +0000949 else
950 Result += " {";
Steve Naroff8749be52007-10-31 22:11:35 +0000951
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +0000952 if (NumIvars > 0) {
953 SourceLocation LocStart = CDecl->getLocStart();
954 SourceLocation LocEnd = CDecl->getLocEnd();
955
956 const char *startBuf = SM->getCharacterData(LocStart);
957 const char *endBuf = SM->getCharacterData(LocEnd);
958 startBuf = strchr(startBuf, '{');
959 assert((startBuf && endBuf)
960 && "SynthesizeObjcInternalStruct - malformed @interface");
961 startBuf++; // past '{'
962 while (startBuf < endBuf) {
963 if (*startBuf == '@') {
964 startBuf = strchr(startBuf, 'p');
965 // FIXME: presence of @public, etc. inside comment results in
966 // this transformation as well, which is still correct c-code.
967 if (!strncmp(startBuf, "public", strlen("public"))) {
968 startBuf += strlen("public");
969 Result += "/* @public */";
970 }
971 else if (!strncmp(startBuf, "private", strlen("private"))) {
972 startBuf += strlen("private");
973 Result += "/* @private */";
974 }
975 else if (!strncmp(startBuf, "protected", strlen("protected"))) {
976 startBuf += strlen("protected");
977 Result += "/* @protected */";
978 }
979 }
980 Result += *startBuf++;
981 }
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000982 }
Fariborz Jahanianfdc08a02007-10-31 17:29:28 +0000983
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000984 Result += "};\n";
985 // Mark this struct as having been generated.
986 if (!ObjcSynthesizedStructs.insert(CDecl))
Fariborz Jahanianaff56d02007-10-31 22:57:04 +0000987 assert(false && "struct already synthesize- SynthesizeObjcInternalStruct");
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000988}
989
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000990// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
991/// class methods.
992void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
993 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000994 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000995 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +0000996 const char *ClassName,
997 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000998 static bool objc_impl_method = false;
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000999 if (NumMethods > 0 && !objc_impl_method) {
1000 /* struct _objc_method {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001001 SEL _cmd;
1002 char *method_types;
1003 void *_imp;
1004 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001005 */
Chris Lattner158ecb92007-10-25 17:07:24 +00001006 Result += "\nstruct _objc_method {\n";
1007 Result += "\tSEL _cmd;\n";
1008 Result += "\tchar *method_types;\n";
1009 Result += "\tvoid *_imp;\n";
1010 Result += "};\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001011
1012 /* struct _objc_method_list {
1013 struct _objc_method_list *next_method;
1014 int method_count;
1015 struct _objc_method method_list[];
1016 }
1017 */
1018 Result += "\nstruct _objc_method_list {\n";
1019 Result += "\tstruct _objc_method_list *next_method;\n";
1020 Result += "\tint method_count;\n";
1021 Result += "\tstruct _objc_method method_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001022 objc_impl_method = true;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +00001023 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001024 // Build _objc_method_list for class's methods if needed
1025 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001026 Result += "\nstatic struct _objc_method_list _OBJC_";
Chris Lattner158ecb92007-10-25 17:07:24 +00001027 Result += prefix;
1028 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
1029 Result += "_METHODS_";
1030 Result += ClassName;
1031 Result += " __attribute__ ((section (\"__OBJC, __";
1032 Result += IsInstanceMethod ? "inst" : "cls";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001033 Result += "_meth\")))= ";
1034 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
1035
1036 Result += "\t,{{(SEL)\"";
1037 Result += Methods[0]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001038 std::string MethodTypeString;
1039 Context->getObjcEncodingForMethodDecl(Methods[0], MethodTypeString);
1040 Result += "\", \"";
1041 Result += MethodTypeString;
1042 Result += "\", 0}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001043 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001044 // TODO: Need method address as 3rd initializer.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001045 Result += "\t ,{(SEL)\"";
1046 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001047 std::string MethodTypeString;
1048 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
1049 Result += "\", \"";
1050 Result += MethodTypeString;
1051 Result += "\", 0}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001052 }
1053 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001054 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001055}
1056
1057/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
1058void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
1059 int NumProtocols,
1060 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001061 const char *ClassName,
1062 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001063 static bool objc_protocol_methods = false;
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001064 if (NumProtocols > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001065 for (int i = 0; i < NumProtocols; i++) {
1066 ObjcProtocolDecl *PDecl = Protocols[i];
1067 // Output struct protocol_methods holder of method selector and type.
1068 if (!objc_protocol_methods &&
1069 (PDecl->getNumInstanceMethods() > 0
1070 || PDecl->getNumClassMethods() > 0)) {
1071 /* struct protocol_methods {
1072 SEL _cmd;
1073 char *method_types;
1074 }
1075 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001076 Result += "\nstruct protocol_methods {\n";
1077 Result += "\tSEL _cmd;\n";
1078 Result += "\tchar *method_types;\n";
1079 Result += "};\n";
1080
1081 /* struct _objc_protocol_method_list {
1082 int protocol_method_count;
1083 struct protocol_methods protocols[];
1084 }
1085 */
1086 Result += "\nstruct _objc_protocol_method_list {\n";
1087 Result += "\tint protocol_method_count;\n";
1088 Result += "\tstruct protocol_methods protocols[];\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001089 objc_protocol_methods = true;
1090 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001091
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001092 // Output instance methods declared in this protocol.
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001093 int NumMethods = PDecl->getNumInstanceMethods();
1094 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001095 Result += "\nstatic struct _objc_protocol_method_list "
1096 "_OBJC_PROTOCOL_INSTANCE_METHODS_";
1097 Result += PDecl->getName();
1098 Result += " __attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
1099 "{\n\t" + utostr(NumMethods) + "\n";
1100
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001101 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001102 Result += "\t,{{(SEL)\"";
1103 Result += Methods[0]->getSelector().getName().c_str();
1104 Result += "\", \"\"}\n";
1105
1106 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001107 Result += "\t ,{(SEL)\"";
1108 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001109 std::string MethodTypeString;
1110 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
1111 Result += "\", \"";
1112 Result += MethodTypeString;
1113 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001114 }
1115 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001116 }
1117
1118 // Output class methods declared in this protocol.
1119 NumMethods = PDecl->getNumClassMethods();
1120 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001121 Result += "\nstatic struct _objc_protocol_method_list "
1122 "_OBJC_PROTOCOL_CLASS_METHODS_";
1123 Result += PDecl->getName();
1124 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
1125 "{\n\t";
1126 Result += utostr(NumMethods);
1127 Result += "\n";
1128
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001129 ObjcMethodDecl **Methods = PDecl->getClassMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001130 Result += "\t,{{(SEL)\"";
1131 Result += Methods[0]->getSelector().getName().c_str();
1132 Result += "\", \"\"}\n";
1133
1134 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001135 Result += "\t ,{(SEL)\"";
1136 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +00001137 std::string MethodTypeString;
1138 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
1139 Result += "\", \"";
1140 Result += MethodTypeString;
1141 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001142 }
1143 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001144 }
1145 // Output:
1146 /* struct _objc_protocol {
1147 // Objective-C 1.0 extensions
1148 struct _objc_protocol_extension *isa;
1149 char *protocol_name;
1150 struct _objc_protocol **protocol_list;
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001151 struct _objc_protocol_method_list *instance_methods;
1152 struct _objc_protocol_method_list *class_methods;
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001153 };
1154 */
1155 static bool objc_protocol = false;
1156 if (!objc_protocol) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001157 Result += "\nstruct _objc_protocol {\n";
1158 Result += "\tstruct _objc_protocol_extension *isa;\n";
1159 Result += "\tchar *protocol_name;\n";
1160 Result += "\tstruct _objc_protocol **protocol_list;\n";
1161 Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
1162 Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
1163 Result += "};\n";
1164
1165 /* struct _objc_protocol_list {
1166 struct _objc_protocol_list *next;
1167 int protocol_count;
1168 struct _objc_protocol *class_protocols[];
1169 }
1170 */
1171 Result += "\nstruct _objc_protocol_list {\n";
1172 Result += "\tstruct _objc_protocol_list *next;\n";
1173 Result += "\tint protocol_count;\n";
1174 Result += "\tstruct _objc_protocol *class_protocols[];\n";
1175 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001176 objc_protocol = true;
1177 }
1178
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001179 Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
1180 Result += PDecl->getName();
1181 Result += " __attribute__ ((section (\"__OBJC, __protocol\")))= "
1182 "{\n\t0, \"";
1183 Result += PDecl->getName();
1184 Result += "\", 0, ";
1185 if (PDecl->getInstanceMethods() > 0) {
1186 Result += "&_OBJC_PROTOCOL_INSTANCE_METHODS_";
1187 Result += PDecl->getName();
1188 Result += ", ";
1189 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001190 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001191 Result += "0, ";
1192 if (PDecl->getClassMethods() > 0) {
1193 Result += "&_OBJC_PROTOCOL_CLASS_METHODS_";
1194 Result += PDecl->getName();
1195 Result += "\n";
1196 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001197 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001198 Result += "0\n";
1199 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001200 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001201 // Output the top lovel protocol meta-data for the class.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001202 Result += "\nstatic struct _objc_protocol_list _OBJC_";
1203 Result += prefix;
1204 Result += "_PROTOCOLS_";
1205 Result += ClassName;
1206 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
1207 "{\n\t0, ";
1208 Result += utostr(NumProtocols);
1209 Result += "\n";
1210
1211 Result += "\t,{&_OBJC_PROTOCOL_";
1212 Result += Protocols[0]->getName();
1213 Result += " \n";
1214
1215 for (int i = 1; i < NumProtocols; i++) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001216 ObjcProtocolDecl *PDecl = Protocols[i];
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001217 Result += "\t ,&_OBJC_PROTOCOL_";
1218 Result += PDecl->getName();
1219 Result += "\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001220 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001221 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001222 }
1223}
1224
1225/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
1226/// implementation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001227void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl,
1228 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001229 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
1230 // Find category declaration for this implementation.
1231 ObjcCategoryDecl *CDecl;
1232 for (CDecl = ClassDecl->getCategoryList(); CDecl;
1233 CDecl = CDecl->getNextClassCategory())
1234 if (CDecl->getIdentifier() == IDecl->getIdentifier())
1235 break;
1236 assert(CDecl && "RewriteObjcCategoryImplDecl - bad category");
1237
1238 char *FullCategoryName = (char*)alloca(
1239 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
1240 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
1241
1242 // Build _objc_method_list for class's instance methods if needed
1243 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
1244 IDecl->getNumInstanceMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +00001245 true,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001246 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001247
1248 // Build _objc_method_list for class's class methods if needed
1249 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
1250 IDecl->getNumClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +00001251 false,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001252 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001253
1254 // Protocols referenced in class declaration?
1255 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
1256 CDecl->getNumReferencedProtocols(),
1257 "CATEGORY",
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001258 FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001259
1260 /* struct _objc_category {
1261 char *category_name;
1262 char *class_name;
1263 struct _objc_method_list *instance_methods;
1264 struct _objc_method_list *class_methods;
1265 struct _objc_protocol_list *protocols;
1266 // Objective-C 1.0 extensions
1267 uint32_t size; // sizeof (struct _objc_category)
1268 struct _objc_property_list *instance_properties; // category's own
1269 // @property decl.
1270 };
1271 */
1272
1273 static bool objc_category = false;
1274 if (!objc_category) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001275 Result += "\nstruct _objc_category {\n";
1276 Result += "\tchar *category_name;\n";
1277 Result += "\tchar *class_name;\n";
1278 Result += "\tstruct _objc_method_list *instance_methods;\n";
1279 Result += "\tstruct _objc_method_list *class_methods;\n";
1280 Result += "\tstruct _objc_protocol_list *protocols;\n";
1281 Result += "\tunsigned int size;\n";
1282 Result += "\tstruct _objc_property_list *instance_properties;\n";
1283 Result += "};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001284 objc_category = true;
Fariborz Jahaniane887c092007-10-22 21:41:37 +00001285 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001286 Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
1287 Result += FullCategoryName;
1288 Result += " __attribute__ ((section (\"__OBJC, __category\")))= {\n\t\"";
1289 Result += IDecl->getName();
1290 Result += "\"\n\t, \"";
1291 Result += ClassDecl->getName();
1292 Result += "\"\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001293
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001294 if (IDecl->getNumInstanceMethods() > 0) {
1295 Result += "\t, (struct _objc_method_list *)"
1296 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
1297 Result += FullCategoryName;
1298 Result += "\n";
1299 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001300 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001301 Result += "\t, 0\n";
1302 if (IDecl->getNumClassMethods() > 0) {
1303 Result += "\t, (struct _objc_method_list *)"
1304 "&_OBJC_CATEGORY_CLASS_METHODS_";
1305 Result += FullCategoryName;
1306 Result += "\n";
1307 }
1308 else
1309 Result += "\t, 0\n";
1310
1311 if (CDecl->getNumReferencedProtocols() > 0) {
1312 Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
1313 Result += FullCategoryName;
1314 Result += "\n";
1315 }
1316 else
1317 Result += "\t, 0\n";
1318 Result += "\t, sizeof(struct _objc_category), 0\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001319}
1320
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001321/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
1322/// ivar offset.
1323void RewriteTest::SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
1324 ObjcIvarDecl *ivar,
1325 std::string &Result) {
Fariborz Jahanian909f02a2007-11-05 17:47:33 +00001326 Result += "offsetof(struct ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001327 Result += IDecl->getName();
1328 Result += ", ";
1329 Result += ivar->getName();
1330 Result += ")";
1331}
1332
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001333//===----------------------------------------------------------------------===//
1334// Meta Data Emission
1335//===----------------------------------------------------------------------===//
1336
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001337void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
1338 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001339 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
1340
1341 // Build _objc_ivar_list metadata for classes ivars if needed
1342 int NumIvars = IDecl->getImplDeclNumIvars() > 0
1343 ? IDecl->getImplDeclNumIvars()
1344 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
1345
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00001346 SynthesizeObjcInternalStruct(CDecl, Result);
1347
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001348 if (NumIvars > 0) {
1349 static bool objc_ivar = false;
1350 if (!objc_ivar) {
1351 /* struct _objc_ivar {
1352 char *ivar_name;
1353 char *ivar_type;
1354 int ivar_offset;
1355 };
1356 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001357 Result += "\nstruct _objc_ivar {\n";
1358 Result += "\tchar *ivar_name;\n";
1359 Result += "\tchar *ivar_type;\n";
1360 Result += "\tint ivar_offset;\n";
1361 Result += "};\n";
1362
1363 /* struct _objc_ivar_list {
1364 int ivar_count;
1365 struct _objc_ivar ivar_list[];
1366 };
1367 */
1368 Result += "\nstruct _objc_ivar_list {\n";
1369 Result += "\tint ivar_count;\n";
1370 Result += "\tstruct _objc_ivar ivar_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001371 objc_ivar = true;
1372 }
1373
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001374 Result += "\nstatic struct _objc_ivar_list _OBJC_INSTANCE_VARIABLES_";
1375 Result += IDecl->getName();
1376 Result += " __attribute__ ((section (\"__OBJC, __instance_vars\")))= "
1377 "{\n\t";
1378 Result += utostr(NumIvars);
1379 Result += "\n";
1380
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001381 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
1382 ? IDecl->getImplDeclIVars()
1383 : CDecl->getIntfDeclIvars();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001384 Result += "\t,{{\"";
1385 Result += Ivars[0]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +00001386 Result += "\", \"";
1387 std::string StrEncoding;
1388 Context->getObjcEncodingForType(Ivars[0]->getType(), StrEncoding);
1389 Result += StrEncoding;
1390 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001391 SynthesizeIvarOffsetComputation(IDecl, Ivars[0], Result);
1392 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001393 for (int i = 1; i < NumIvars; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001394 Result += "\t ,{\"";
1395 Result += Ivars[i]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +00001396 Result += "\", \"";
1397 std::string StrEncoding;
1398 Context->getObjcEncodingForType(Ivars[i]->getType(), StrEncoding);
1399 Result += StrEncoding;
1400 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001401 SynthesizeIvarOffsetComputation(IDecl, Ivars[i], Result);
1402 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001403 }
1404
1405 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001406 }
1407
1408 // Build _objc_method_list for class's instance methods if needed
1409 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
1410 IDecl->getNumInstanceMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001411 true,
1412 "", IDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001413
1414 // Build _objc_method_list for class's class methods if needed
1415 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +00001416 IDecl->getNumClassMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001417 false,
1418 "", IDecl->getName(), Result);
1419
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001420 // Protocols referenced in class declaration?
1421 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
1422 CDecl->getNumIntfRefProtocols(),
1423 "CLASS",
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001424 CDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001425
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001426
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001427 // Declaration of class/meta-class metadata
1428 /* struct _objc_class {
1429 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001430 const char *super_class_name;
1431 char *name;
1432 long version;
1433 long info;
1434 long instance_size;
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001435 struct _objc_ivar_list *ivars;
1436 struct _objc_method_list *methods;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001437 struct objc_cache *cache;
1438 struct objc_protocol_list *protocols;
1439 const char *ivar_layout;
1440 struct _objc_class_ext *ext;
1441 };
1442 */
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001443 static bool objc_class = false;
1444 if (!objc_class) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001445 Result += "\nstruct _objc_class {\n";
1446 Result += "\tstruct _objc_class *isa;\n";
1447 Result += "\tconst char *super_class_name;\n";
1448 Result += "\tchar *name;\n";
1449 Result += "\tlong version;\n";
1450 Result += "\tlong info;\n";
1451 Result += "\tlong instance_size;\n";
1452 Result += "\tstruct _objc_ivar_list *ivars;\n";
1453 Result += "\tstruct _objc_method_list *methods;\n";
1454 Result += "\tstruct objc_cache *cache;\n";
1455 Result += "\tstruct _objc_protocol_list *protocols;\n";
1456 Result += "\tconst char *ivar_layout;\n";
1457 Result += "\tstruct _objc_class_ext *ext;\n";
1458 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001459 objc_class = true;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001460 }
1461
1462 // Meta-class metadata generation.
1463 ObjcInterfaceDecl *RootClass = 0;
1464 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
1465 while (SuperClass) {
1466 RootClass = SuperClass;
1467 SuperClass = SuperClass->getSuperClass();
1468 }
1469 SuperClass = CDecl->getSuperClass();
1470
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001471 Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
1472 Result += CDecl->getName();
1473 Result += " __attribute__ ((section (\"__OBJC, __meta_class\")))= "
1474 "{\n\t(struct _objc_class *)\"";
1475 Result += (RootClass ? RootClass->getName() : CDecl->getName());
1476 Result += "\"";
1477
1478 if (SuperClass) {
1479 Result += ", \"";
1480 Result += SuperClass->getName();
1481 Result += "\", \"";
1482 Result += CDecl->getName();
1483 Result += "\"";
1484 }
1485 else {
1486 Result += ", 0, \"";
1487 Result += CDecl->getName();
1488 Result += "\"";
1489 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001490 // TODO: 'ivars' field for root class is currently set to 0.
1491 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001492 Result += ", 0,2, sizeof(struct _objc_class), 0";
1493 if (CDecl->getNumClassMethods() > 0) {
1494 Result += "\n\t, &_OBJC_CLASS_METHODS_";
1495 Result += CDecl->getName();
1496 Result += "\n";
1497 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001498 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001499 Result += ", 0\n";
1500 if (CDecl->getNumIntfRefProtocols() > 0) {
1501 Result += "\t,0, &_OBJC_CLASS_PROTOCOLS_";
1502 Result += CDecl->getName();
1503 Result += ",0,0\n";
1504 }
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001505 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001506 Result += "\t,0,0,0,0\n";
1507 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001508
1509 // class metadata generation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001510 Result += "\nstatic struct _objc_class _OBJC_CLASS_";
1511 Result += CDecl->getName();
1512 Result += " __attribute__ ((section (\"__OBJC, __class\")))= "
1513 "{\n\t&_OBJC_METACLASS_";
1514 Result += CDecl->getName();
1515 if (SuperClass) {
1516 Result += ", \"";
1517 Result += SuperClass->getName();
1518 Result += "\", \"";
1519 Result += CDecl->getName();
1520 Result += "\"";
1521 }
1522 else {
1523 Result += ", 0, \"";
1524 Result += CDecl->getName();
1525 Result += "\"";
1526 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001527 // 'info' field is initialized to CLS_CLASS(1) for class
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00001528 Result += ", 0,1";
1529 if (!ObjcSynthesizedStructs.count(CDecl))
1530 Result += ",0";
1531 else {
1532 // class has size. Must synthesize its size.
Fariborz Jahanian909f02a2007-11-05 17:47:33 +00001533 Result += ",sizeof(struct ";
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00001534 Result += CDecl->getName();
1535 Result += ")";
1536 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001537 if (NumIvars > 0) {
1538 Result += ", &_OBJC_INSTANCE_VARIABLES_";
1539 Result += CDecl->getName();
1540 Result += "\n\t";
1541 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001542 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001543 Result += ",0";
1544 if (IDecl->getNumInstanceMethods() > 0) {
1545 Result += ", &_OBJC_INSTANCE_METHODS_";
1546 Result += CDecl->getName();
1547 Result += ", 0\n\t";
1548 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001549 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001550 Result += ",0,0";
1551 if (CDecl->getNumIntfRefProtocols() > 0) {
1552 Result += ", &_OBJC_CLASS_PROTOCOLS_";
1553 Result += CDecl->getName();
1554 Result += ", 0,0\n";
1555 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001556 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001557 Result += ",0,0,0\n";
1558 Result += "};\n";
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001559}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001560
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001561void RewriteTest::WriteObjcMetaData(std::string &Result) {
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001562 int ClsDefCount = ClassImplementation.size();
1563 int CatDefCount = CategoryImplementation.size();
1564 if (ClsDefCount == 0 && CatDefCount == 0)
1565 return;
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001566
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001567 // TODO: This is temporary until we decide how to access objc types in a
1568 // c program
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001569 Result += "#include <Objc/objc.h>\n";
1570 // This is needed for use of offsetof
1571 Result += "#include <stddef.h>\n";
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001572
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001573 // For each implemented class, write out all its meta data.
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001574 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001575 RewriteObjcClassMetaData(ClassImplementation[i], Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001576
1577 // For each implemented category, write out all its meta data.
1578 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001579 RewriteObjcCategoryImplDecl(CategoryImplementation[i], Result);
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001580
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001581 // Write objc_symtab metadata
1582 /*
1583 struct _objc_symtab
1584 {
1585 long sel_ref_cnt;
1586 SEL *refs;
1587 short cls_def_cnt;
1588 short cat_def_cnt;
1589 void *defs[cls_def_cnt + cat_def_cnt];
1590 };
1591 */
1592
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001593 Result += "\nstruct _objc_symtab {\n";
1594 Result += "\tlong sel_ref_cnt;\n";
1595 Result += "\tSEL *refs;\n";
1596 Result += "\tshort cls_def_cnt;\n";
1597 Result += "\tshort cat_def_cnt;\n";
1598 Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
1599 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001600
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001601 Result += "static struct _objc_symtab "
1602 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n";
1603 Result += "\t0, 0, " + utostr(ClsDefCount)
1604 + ", " + utostr(CatDefCount) + "\n";
1605 for (int i = 0; i < ClsDefCount; i++) {
1606 Result += "\t,&_OBJC_CLASS_";
1607 Result += ClassImplementation[i]->getName();
1608 Result += "\n";
1609 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001610
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001611 for (int i = 0; i < CatDefCount; i++) {
1612 Result += "\t,&_OBJC_CATEGORY_";
1613 Result += CategoryImplementation[i]->getClassInterface()->getName();
1614 Result += "_";
1615 Result += CategoryImplementation[i]->getName();
1616 Result += "\n";
1617 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001618
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001619 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001620
1621 // Write objc_module metadata
1622
1623 /*
1624 struct _objc_module {
1625 long version;
1626 long size;
1627 const char *name;
1628 struct _objc_symtab *symtab;
1629 }
1630 */
1631
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001632 Result += "\nstruct _objc_module {\n";
1633 Result += "\tlong version;\n";
1634 Result += "\tlong size;\n";
1635 Result += "\tconst char *name;\n";
1636 Result += "\tstruct _objc_symtab *symtab;\n";
1637 Result += "};\n\n";
1638 Result += "static struct _objc_module "
1639 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001640 Result += "\t" + utostr(OBJC_ABI_VERSION) +
1641 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001642 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001643}
Chris Lattner311ff022007-10-16 22:36:42 +00001644