aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2011-12-08 18:25:15 +0000
committerFariborz Jahanian <fjahanian@apple.com>2011-12-08 18:25:15 +0000
commitd5c3fa29c6a06ed9c74e03b4a96f786cbc156b7c (patch)
tree79c2eee7667d4863d0ba0e216685e6fd8f85c8a5
parent489ad43b77c10a98df80f1395de81e3f52697e76 (diff)
More refactoring of objective-C rewriter.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146160 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Rewrite/RewriteObjC.cpp2027
1 files changed, 1036 insertions, 991 deletions
diff --git a/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp
index 81f413f857..f50282ef8b 100644
--- a/lib/Rewrite/RewriteObjC.cpp
+++ b/lib/Rewrite/RewriteObjC.cpp
@@ -32,6 +32,8 @@ using llvm::utostr;
namespace {
class RewriteObjC : public ASTConsumer {
+ protected:
+
enum {
BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
block, ... */
@@ -54,7 +56,7 @@ namespace {
BLOCK_HAS_DESCRIPTOR = (1 << 29)
};
static const int OBJC_ABI_VERSION = 7;
-
+
Rewriter Rewrite;
DiagnosticsEngine &Diags;
const LangOptions &LangOpts;
@@ -72,7 +74,6 @@ namespace {
TypeDecl *ProtocolTypeDecl;
VarDecl *GlobalVarDecl;
unsigned RewriteFailedDiag;
- unsigned TryFinallyContainsReturnDiag;
// ObjC string constant support.
unsigned NumObjCStringLiterals;
VarDecl *ConstantStringClassReference;
@@ -81,6 +82,7 @@ namespace {
// ObjC foreach break/continue generation support.
int BcLabelCount;
+ unsigned TryFinallyContainsReturnDiag;
// Needed for super.
ObjCMethodDecl *CurMethodDef;
RecordDecl *SuperStructDecl;
@@ -156,9 +158,9 @@ namespace {
R.DisableReplaceStmt = SavedValue;
}
};
+ void InitializeCommon(ASTContext &context);
public:
- virtual void Initialize(ASTContext &context);
// Top Level Driver code.
virtual bool HandleTopLevelDecl(DeclGroupRef D) {
@@ -284,7 +286,6 @@ namespace {
// Expression Rewriting.
Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
- Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
@@ -301,31 +302,7 @@ namespace {
Stmt *RewriteBreakStmt(BreakStmt *S);
Stmt *RewriteContinueStmt(ContinueStmt *S);
void RewriteCastExpr(CStyleCastExpr *CE);
-
- // Metadata Rewriting.
- void RewriteMetaDataIntoBuffer(std::string &Result);
- void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
- std::string &Result);
-
- void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
- std::string &Result);
-
- template<typename MethodIterator>
- void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
- MethodIterator MethodEnd,
- bool IsInstanceMethod,
- StringRef prefix,
- StringRef ClassName,
- std::string &Result);
-
- void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
- StringRef prefix,
- StringRef ClassName,
- std::string &Result);
- void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,
- StringRef prefix,
- StringRef ClassName,
- std::string &Result);
+
// Block rewriting.
void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
@@ -338,8 +315,28 @@ namespace {
void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
std::string &Result);
- void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
- std::string &Result);
+
+ virtual void Initialize(ASTContext &context) = 0;
+
+ // Metadata Rewriting.
+ virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0;
+ virtual void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,
+ StringRef prefix,
+ StringRef ClassName,
+ std::string &Result) = 0;
+ virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
+ std::string &Result) = 0;
+ virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
+ StringRef prefix,
+ StringRef ClassName,
+ std::string &Result) = 0;
+ virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
+ std::string &Result) = 0;
+
+ // Rewriting ivar access
+ virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0;
+ virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
+ std::string &Result) = 0;
// Misc. AST transformation routines. Somtimes they end up calling
// rewriting routines on the new ASTs.
@@ -488,6 +485,45 @@ namespace {
SourceLocation(), SourceLocation());
}
};
+
+ class RewriteObjCFragileABI : public RewriteObjC {
+ public:
+
+ RewriteObjCFragileABI(std::string inFile, raw_ostream *OS,
+ DiagnosticsEngine &D, const LangOptions &LOpts,
+ bool silenceMacroWarn) : RewriteObjC(inFile, OS,
+ D, LOpts,
+ silenceMacroWarn) {}
+
+ ~RewriteObjCFragileABI() {}
+ virtual void Initialize(ASTContext &context);
+
+ // Rewriting metadata
+ template<typename MethodIterator>
+ void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
+ MethodIterator MethodEnd,
+ bool IsInstanceMethod,
+ StringRef prefix,
+ StringRef ClassName,
+ std::string &Result);
+ virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
+ StringRef prefix,
+ StringRef ClassName,
+ std::string &Result);
+ virtual void RewriteObjCProtocolListMetaData(
+ const ObjCList<ObjCProtocolDecl> &Prots,
+ StringRef prefix, StringRef ClassName, std::string &Result);
+ virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
+ std::string &Result);
+ virtual void RewriteMetaDataIntoBuffer(std::string &Result);
+ virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
+ std::string &Result);
+
+ // Rewriting ivar
+ virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
+ std::string &Result);
+ virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
+ };
}
void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
@@ -543,10 +579,15 @@ ASTConsumer *clang::CreateObjCRewriter(const std::string& InFile,
DiagnosticsEngine &Diags,
const LangOptions &LOpts,
bool SilenceRewriteMacroWarning) {
- return new RewriteObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
+ if (true /*!LOpts.ObjCNonFragileABI*/)
+ return new RewriteObjCFragileABI(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
+ else {
+ assert(false && "objective-C rewriter for nonfragile ABI = NYI");
+ return 0;
+ }
}
-void RewriteObjC::Initialize(ASTContext &context) {
+void RewriteObjC::InitializeCommon(ASTContext &context) {
Context = &context;
SM = &Context->getSourceManager();
TUDecl = Context->getTranslationUnitDecl();
@@ -584,120 +625,8 @@ void RewriteObjC::Initialize(ASTContext &context) {
MainFileEnd = MainBuf->getBufferEnd();
Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOptions());
-
- // declaring objc_selector outside the parameter list removes a silly
- // scope related warning...
- if (IsHeader)
- Preamble = "#pragma once\n";
- Preamble += "struct objc_selector; struct objc_class;\n";
- Preamble += "struct __rw_objc_super { struct objc_object *object; ";
- Preamble += "struct objc_object *superClass; ";
- if (LangOpts.MicrosoftExt) {
- // Add a constructor for creating temporary objects.
- Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "
- ": ";
- Preamble += "object(o), superClass(s) {} ";
- }
- Preamble += "};\n";
- Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
- Preamble += "typedef struct objc_object Protocol;\n";
- Preamble += "#define _REWRITER_typedef_Protocol\n";
- Preamble += "#endif\n";
- if (LangOpts.MicrosoftExt) {
- Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
- Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
- } else
- Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
- Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
- Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
- Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
- Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
- Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
- Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
- Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
- Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
- Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
- Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
- Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
- Preamble += "(const char *);\n";
- Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
- Preamble += "(struct objc_class *);\n";
- Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
- Preamble += "(const char *);\n";
- Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
- Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
- Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
- Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
- Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match";
- Preamble += "(struct objc_class *, struct objc_object *);\n";
- // @synchronized hooks.
- Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n";
- Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n";
- Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
- Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
- Preamble += "struct __objcFastEnumerationState {\n\t";
- Preamble += "unsigned long state;\n\t";
- Preamble += "void **itemsPtr;\n\t";
- Preamble += "unsigned long *mutationsPtr;\n\t";
- Preamble += "unsigned long extra[5];\n};\n";
- Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
- Preamble += "#define __FASTENUMERATIONSTATE\n";
- Preamble += "#endif\n";
- Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
- Preamble += "struct __NSConstantStringImpl {\n";
- Preamble += " int *isa;\n";
- Preamble += " int flags;\n";
- Preamble += " char *str;\n";
- Preamble += " long length;\n";
- Preamble += "};\n";
- Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
- Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
- Preamble += "#else\n";
- Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
- Preamble += "#endif\n";
- Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
- Preamble += "#endif\n";
- // Blocks preamble.
- Preamble += "#ifndef BLOCK_IMPL\n";
- Preamble += "#define BLOCK_IMPL\n";
- Preamble += "struct __block_impl {\n";
- Preamble += " void *isa;\n";
- Preamble += " int Flags;\n";
- Preamble += " int Reserved;\n";
- Preamble += " void *FuncPtr;\n";
- Preamble += "};\n";
- Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
- Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
- Preamble += "extern \"C\" __declspec(dllexport) "
- "void _Block_object_assign(void *, const void *, const int);\n";
- Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
- Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
- Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
- Preamble += "#else\n";
- Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
- Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
- Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
- Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
- Preamble += "#endif\n";
- Preamble += "#endif\n";
- if (LangOpts.MicrosoftExt) {
- Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
- Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
- Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests.
- Preamble += "#define __attribute__(X)\n";
- Preamble += "#endif\n";
- Preamble += "#define __weak\n";
- }
- else {
- Preamble += "#define __block\n";
- Preamble += "#define __weak\n";
- }
- // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
- // as this avoids warning in any 64bit/32bit compilation model.
- Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
}
-
//===----------------------------------------------------------------------===//
// Top Level Driver Code
//===----------------------------------------------------------------------===//
@@ -1436,98 +1365,6 @@ Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {
return Replacement;
}
-Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
- SourceRange OldRange = IV->getSourceRange();
- Expr *BaseExpr = IV->getBase();
-
- // Rewrite the base, but without actually doing replaces.
- {
- DisableReplaceStmtScope S(*this);
- BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
- IV->setBase(BaseExpr);
- }
-
- ObjCIvarDecl *D = IV->getDecl();
-
- Expr *Replacement = IV;
- if (CurMethodDef) {
- if (BaseExpr->getType()->isObjCObjectPointerType()) {
- const ObjCInterfaceType *iFaceDecl =
- dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
- assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
- // lookup which class implements the instance variable.
- ObjCInterfaceDecl *clsDeclared = 0;
- iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
- clsDeclared);
- assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
-
- // Synthesize an explicit cast to gain access to the ivar.
- std::string RecName = clsDeclared->getIdentifier()->getName();
- RecName += "_IMPL";
- IdentifierInfo *II = &Context->Idents.get(RecName);
- RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
- SourceLocation(), SourceLocation(),
- II);
- assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
- QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
- CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
- CK_BitCast,
- IV->getBase());
- // Don't forget the parens to enforce the proper binding.
- ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(),
- OldRange.getEnd(),
- castExpr);
- if (IV->isFreeIvar() &&
- CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) {
- MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
- IV->getLocation(),
- D->getType(),
- VK_LValue, OK_Ordinary);
- Replacement = ME;
- } else {
- IV->setBase(PE);
- }
- }
- } else { // we are outside a method.
- assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");
-
- // Explicit ivar refs need to have a cast inserted.
- // FIXME: consider sharing some of this code with the code above.
- if (BaseExpr->getType()->isObjCObjectPointerType()) {
- const ObjCInterfaceType *iFaceDecl =
- dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
- // lookup which class implements the instance variable.
- ObjCInterfaceDecl *clsDeclared = 0;
- iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
- clsDeclared);
- assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
-
- // Synthesize an explicit cast to gain access to the ivar.
- std::string RecName = clsDeclared->getIdentifier()->getName();
- RecName += "_IMPL";
- IdentifierInfo *II = &Context->Idents.get(RecName);
- RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
- SourceLocation(), SourceLocation(),
- II);
- assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
- QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
- CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
- CK_BitCast,
- IV->getBase());
- // Don't forget the parens to enforce the proper binding.
- ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
- IV->getBase()->getLocEnd(), castExpr);
- // Cannot delete IV->getBase(), since PE points to it.
- // Replace the old base with the cast. This is important when doing
- // embedded rewrites. For example, [newInv->_container addObject:0].
- IV->setBase(PE);
- }
- }
-
- ReplaceStmtWithRange(IV, Replacement, OldRange);
- return Replacement;
-}
-
/// SynthCountByEnumWithState - To print:
/// ((unsigned int (*)
/// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
@@ -3405,667 +3242,10 @@ void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct");
}
-// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
-/// class methods.
-template<typename MethodIterator>
-void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
- MethodIterator MethodEnd,
- bool IsInstanceMethod,
- StringRef prefix,
- StringRef ClassName,
- std::string &Result) {
- if (MethodBegin == MethodEnd) return;
-
- if (!objc_impl_method) {
- /* struct _objc_method {
- SEL _cmd;
- char *method_types;
- void *_imp;
- }
- */
- Result += "\nstruct _objc_method {\n";
- Result += "\tSEL _cmd;\n";
- Result += "\tchar *method_types;\n";
- Result += "\tvoid *_imp;\n";
- Result += "};\n";
-
- objc_impl_method = true;
- }
-
- // Build _objc_method_list for class's methods if needed
-
- /* struct {
- struct _objc_method_list *next_method;
- int method_count;
- struct _objc_method method_list[];
- }
- */
- unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
- Result += "\nstatic struct {\n";
- Result += "\tstruct _objc_method_list *next_method;\n";
- Result += "\tint method_count;\n";
- Result += "\tstruct _objc_method method_list[";
- Result += utostr(NumMethods);
- Result += "];\n} _OBJC_";
- Result += prefix;
- Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
- Result += "_METHODS_";
- Result += ClassName;
- Result += " __attribute__ ((used, section (\"__OBJC, __";
- Result += IsInstanceMethod ? "inst" : "cls";
- Result += "_meth\")))= ";
- Result += "{\n\t0, " + utostr(NumMethods) + "\n";
-
- Result += "\t,{{(SEL)\"";
- Result += (*MethodBegin)->getSelector().getAsString().c_str();
- std::string MethodTypeString;
- Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
- Result += "\", \"";
- Result += MethodTypeString;
- Result += "\", (void *)";
- Result += MethodInternalNames[*MethodBegin];
- Result += "}\n";
- for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
- Result += "\t ,{(SEL)\"";
- Result += (*MethodBegin)->getSelector().getAsString().c_str();
- std::string MethodTypeString;
- Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
- Result += "\", \"";
- Result += MethodTypeString;
- Result += "\", (void *)";
- Result += MethodInternalNames[*MethodBegin];
- Result += "}\n";
- }
- Result += "\t }\n};\n";
-}
-
-/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
-void RewriteObjC::
-RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, StringRef prefix,
- StringRef ClassName, std::string &Result) {
- static bool objc_protocol_methods = false;
-
- // Output struct protocol_methods holder of method selector and type.
- if (!objc_protocol_methods && !PDecl->isForwardDecl()) {
- /* struct protocol_methods {
- SEL _cmd;
- char *method_types;
- }
- */
- Result += "\nstruct _protocol_methods {\n";
- Result += "\tstruct objc_selector *_cmd;\n";
- Result += "\tchar *method_types;\n";
- Result += "};\n";
-
- objc_protocol_methods = true;
- }
- // Do not synthesize the protocol more than once.
- if (ObjCSynthesizedProtocols.count(PDecl))
- return;
-
- if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
- unsigned NumMethods = std::distance(PDecl->instmeth_begin(),
- PDecl->instmeth_end());
- /* struct _objc_protocol_method_list {
- int protocol_method_count;
- struct protocol_methods protocols[];
- }
- */
- Result += "\nstatic struct {\n";
- Result += "\tint protocol_method_count;\n";
- Result += "\tstruct _protocol_methods protocol_methods[";
- Result += utostr(NumMethods);
- Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
- Result += PDecl->getNameAsString();
- Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
- "{\n\t" + utostr(NumMethods) + "\n";
-
- // Output instance methods declared in this protocol.
- for (ObjCProtocolDecl::instmeth_iterator
- I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
- I != E; ++I) {
- if (I == PDecl->instmeth_begin())
- Result += "\t ,{{(struct objc_selector *)\"";
- else
- Result += "\t ,{(struct objc_selector *)\"";
- Result += (*I)->getSelector().getAsString();
- std::string MethodTypeString;
- Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
- Result += "\", \"";
- Result += MethodTypeString;
- Result += "\"}\n";
- }
- Result += "\t }\n};\n";
- }
-
- // Output class methods declared in this protocol.
- unsigned NumMethods = std::distance(PDecl->classmeth_begin(),
- PDecl->classmeth_end());
- if (NumMethods > 0) {
- /* struct _objc_protocol_method_list {
- int protocol_method_count;
- struct protocol_methods protocols[];
- }
- */
- Result += "\nstatic struct {\n";
- Result += "\tint protocol_method_count;\n";
- Result += "\tstruct _protocol_methods protocol_methods[";
- Result += utostr(NumMethods);
- Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
- Result += PDecl->getNameAsString();
- Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
- "{\n\t";
- Result += utostr(NumMethods);
- Result += "\n";
-
- // Output instance methods declared in this protocol.
- for (ObjCProtocolDecl::classmeth_iterator
- I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
- I != E; ++I) {
- if (I == PDecl->classmeth_begin())
- Result += "\t ,{{(struct objc_selector *)\"";
- else
- Result += "\t ,{(struct objc_selector *)\"";
- Result += (*I)->getSelector().getAsString();
- std::string MethodTypeString;
- Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
- Result += "\", \"";
- Result += MethodTypeString;
- Result += "\"}\n";
- }
- Result += "\t }\n};\n";
- }
-
- // Output:
- /* struct _objc_protocol {
- // Objective-C 1.0 extensions
- struct _objc_protocol_extension *isa;
- char *protocol_name;
- struct _objc_protocol **protocol_list;
- struct _objc_protocol_method_list *instance_methods;
- struct _objc_protocol_method_list *class_methods;
- };
- */
- static bool objc_protocol = false;
- if (!objc_protocol) {
- Result += "\nstruct _objc_protocol {\n";
- Result += "\tstruct _objc_protocol_extension *isa;\n";
- Result += "\tchar *protocol_name;\n";
- Result += "\tstruct _objc_protocol **protocol_list;\n";
- Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
- Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
- Result += "};\n";
-
- objc_protocol = true;
- }
-
- Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
- Result += PDecl->getNameAsString();
- Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
- "{\n\t0, \"";
- Result += PDecl->getNameAsString();
- Result += "\", 0, ";
- if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
- Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
- Result += PDecl->getNameAsString();
- Result += ", ";
- }
- else
- Result += "0, ";
- if (PDecl->classmeth_begin() != PDecl->classmeth_end()) {
- Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
- Result += PDecl->getNameAsString();
- Result += "\n";
- }
- else
- Result += "0\n";
- Result += "};\n";
-
- // Mark this protocol as having been generated.
- if (!ObjCSynthesizedProtocols.insert(PDecl))
- llvm_unreachable("protocol already synthesized");
-
-}
-
-void RewriteObjC::
-RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Protocols,
- StringRef prefix, StringRef ClassName,
- std::string &Result) {
- if (Protocols.empty()) return;
-
- for (unsigned i = 0; i != Protocols.size(); i++)
- RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
-
- // Output the top lovel protocol meta-data for the class.
- /* struct _objc_protocol_list {
- struct _objc_protocol_list *next;
- int protocol_count;
- struct _objc_protocol *class_protocols[];
- }
- */
- Result += "\nstatic struct {\n";
- Result += "\tstruct _objc_protocol_list *next;\n";
- Result += "\tint protocol_count;\n";
- Result += "\tstruct _objc_protocol *class_protocols[";
- Result += utostr(Protocols.size());
- Result += "];\n} _OBJC_";
- Result += prefix;
- Result += "_PROTOCOLS_";
- Result += ClassName;
- Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
- "{\n\t0, ";
- Result += utostr(Protocols.size());
- Result += "\n";
-
- Result += "\t,{&_OBJC_PROTOCOL_";
- Result += Protocols[0]->getNameAsString();
- Result += " \n";
-
- for (unsigned i = 1; i != Protocols.size(); i++) {
- Result += "\t ,&_OBJC_PROTOCOL_";
- Result += Protocols[i]->getNameAsString();
- Result += "\n";
- }
- Result += "\t }\n};\n";
-}
-
-
-/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
-/// implementation.
-void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
- std::string &Result) {
- ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
- // Find category declaration for this implementation.
- ObjCCategoryDecl *CDecl;
- for (CDecl = ClassDecl->getCategoryList(); CDecl;
- CDecl = CDecl->getNextClassCategory())
- if (CDecl->getIdentifier() == IDecl->getIdentifier())
- break;
-
- std::string FullCategoryName = ClassDecl->getNameAsString();
- FullCategoryName += '_';
- FullCategoryName += IDecl->getNameAsString();
-
- // Build _objc_method_list for class's instance methods if needed
- SmallVector<ObjCMethodDecl *, 32>
- InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
-
- // If any of our property implementations have associated getters or
- // setters, produce metadata for them as well.
- for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
- PropEnd = IDecl->propimpl_end();
- Prop != PropEnd; ++Prop) {
- if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
- continue;
- if (!(*Prop)->getPropertyIvarDecl())
- continue;
- ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
- if (!PD)
- continue;
- if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
- InstanceMethods.push_back(Getter);
- if (PD->isReadOnly())
- continue;
- if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
- InstanceMethods.push_back(Setter);
- }
- RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
- true, "CATEGORY_", FullCategoryName.c_str(),
- Result);
-
- // Build _objc_method_list for class's class methods if needed
- RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
- false, "CATEGORY_", FullCategoryName.c_str(),
- Result);
-
- // Protocols referenced in class declaration?
- // Null CDecl is case of a category implementation with no category interface
- if (CDecl)
- RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY",
- FullCategoryName, Result);
- /* struct _objc_category {
- char *category_name;
- char *class_name;
- struct _objc_method_list *instance_methods;
- struct _objc_method_list *class_methods;
- struct _objc_protocol_list *protocols;
- // Objective-C 1.0 extensions
- uint32_t size; // sizeof (struct _objc_category)
- struct _objc_property_list *instance_properties; // category's own
- // @property decl.
- };
- */
-
- static bool objc_category = false;
- if (!objc_category) {
- Result += "\nstruct _objc_category {\n";
- Result += "\tchar *category_name;\n";
- Result += "\tchar *class_name;\n";
- Result += "\tstruct _objc_method_list *instance_methods;\n";
- Result += "\tstruct _objc_method_list *class_methods;\n";
- Result += "\tstruct _objc_protocol_list *protocols;\n";
- Result += "\tunsigned int size;\n";
- Result += "\tstruct _objc_property_list *instance_properties;\n";
- Result += "};\n";
- objc_category = true;
- }
- Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
- Result += FullCategoryName;
- Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
- Result += IDecl->getNameAsString();
- Result += "\"\n\t, \"";
- Result += ClassDecl->getNameAsString();
- Result += "\"\n";
-
- if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
- Result += "\t, (struct _objc_method_list *)"
- "&_OBJC_CATEGORY_INSTANCE_METHODS_";
- Result += FullCategoryName;
- Result += "\n";
- }
- else
- Result += "\t, 0\n";
- if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
- Result += "\t, (struct _objc_method_list *)"
- "&_OBJC_CATEGORY_CLASS_METHODS_";
- Result += FullCategoryName;
- Result += "\n";
- }
- else
- Result += "\t, 0\n";
-
- if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) {
- Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
- Result += FullCategoryName;
- Result += "\n";
- }
- else
- Result += "\t, 0\n";
- Result += "\t, sizeof(struct _objc_category), 0\n};\n";
-}
-
-/// RewriteIvarOffsetComputation - This rutine synthesizes computation of
-/// ivar offset.
-void RewriteObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
- std::string &Result) {
- if (ivar->isBitField()) {
- // FIXME: The hack below doesn't work for bitfields. For now, we simply
- // place all bitfields at offset 0.
- Result += "0";
- } else {
- Result += "__OFFSETOFIVAR__(struct ";
- Result += ivar->getContainingInterface()->getNameAsString();
- if (LangOpts.MicrosoftExt)
- Result += "_IMPL";
- Result += ", ";
- Result += ivar->getNameAsString();
- Result += ")";
- }
-}
-
//===----------------------------------------------------------------------===//
// Meta Data Emission
//===----------------------------------------------------------------------===//
-void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
- std::string &Result) {
- ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
-
- // Explicitly declared @interface's are already synthesized.
- if (CDecl->isImplicitInterfaceDecl()) {
- // FIXME: Implementation of a class with no @interface (legacy) doese not
- // produce correct synthesis as yet.
- RewriteObjCInternalStruct(CDecl, Result);
- }
-
- // Build _objc_ivar_list metadata for classes ivars if needed
- unsigned NumIvars = !IDecl->ivar_empty()
- ? IDecl->ivar_size()
- : (CDecl ? CDecl->ivar_size() : 0);
- if (NumIvars > 0) {
- static bool objc_ivar = false;
- if (!objc_ivar) {
- /* struct _objc_ivar {
- char *ivar_name;
- char *ivar_type;
- int ivar_offset;
- };
- */
- Result += "\nstruct _objc_ivar {\n";
- Result += "\tchar *ivar_name;\n";
- Result += "\tchar *ivar_type;\n";
- Result += "\tint ivar_offset;\n";
- Result += "};\n";
-
- objc_ivar = true;
- }
-
- /* struct {
- int ivar_count;
- struct _objc_ivar ivar_list[nIvars];
- };
- */
- Result += "\nstatic struct {\n";
- Result += "\tint ivar_count;\n";
- Result += "\tstruct _objc_ivar ivar_list[";
- Result += utostr(NumIvars);
- Result += "];\n} _OBJC_INSTANCE_VARIABLES_";
- Result += IDecl->getNameAsString();
- Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "
- "{\n\t";
- Result += utostr(NumIvars);
- Result += "\n";
-
- ObjCInterfaceDecl::ivar_iterator IVI, IVE;
- SmallVector<ObjCIvarDecl *, 8> IVars;
- if (!IDecl->ivar_empty()) {
- for (ObjCInterfaceDecl::ivar_iterator
- IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end();
- IV != IVEnd; ++IV)
- IVars.push_back(*IV);
- IVI = IDecl->ivar_begin();
- IVE = IDecl->ivar_end();
- } else {
- IVI = CDecl->ivar_begin();
- IVE = CDecl->ivar_end();
- }
- Result += "\t,{{\"";
- Result += (*IVI)->getNameAsString();
- Result += "\", \"";
- std::string TmpString, StrEncoding;
- Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI);
- QuoteDoublequotes(TmpString, StrEncoding);
- Result += StrEncoding;
- Result += "\", ";
- RewriteIvarOffsetComputation(*IVI, Result);
- Result += "}\n";
- for (++IVI; IVI != IVE; ++IVI) {
- Result += "\t ,{\"";
- Result += (*IVI)->getNameAsString();
- Result += "\", \"";
- std::string TmpString, StrEncoding;
- Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI);
- QuoteDoublequotes(TmpString, StrEncoding);
- Result += StrEncoding;
- Result += "\", ";
- RewriteIvarOffsetComputation((*IVI), Result);
- Result += "}\n";
- }
-
- Result += "\t }\n};\n";
- }
-
- // Build _objc_method_list for class's instance methods if needed
- SmallVector<ObjCMethodDecl *, 32>
- InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
-
- // If any of our property implementations have associated getters or
- // setters, produce metadata for them as well.
- for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
- PropEnd = IDecl->propimpl_end();
- Prop != PropEnd; ++Prop) {
- if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
- continue;
- if (!(*Prop)->getPropertyIvarDecl())
- continue;
- ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
- if (!PD)
- continue;
- if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
- if (!Getter->isDefined())
- InstanceMethods.push_back(Getter);
- if (PD->isReadOnly())
- continue;
- if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
- if (!Setter->isDefined())
- InstanceMethods.push_back(Setter);
- }
- RewriteObjCMethodsMetaData(InstanceMethods.begin(), Instan