modern objc translator: category metadata related

patch.

llvm-svn: 150825
This commit is contained in:
Fariborz Jahanian 2012-02-17 18:40:41 +00:00
parent 0c1941cb05
commit f20550543f
1 changed files with 118 additions and 70 deletions

View File

@ -5597,6 +5597,61 @@ static void Write_class_t(ASTContext *Context, std::string &Result,
Result += ",\n};\n"; Result += ",\n};\n";
} }
static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,
std::string &Result,
StringRef CatName,
StringRef ClassName,
ArrayRef<ObjCMethodDecl *> InstanceMethods,
ArrayRef<ObjCMethodDecl *> ClassMethods,
ArrayRef<ObjCProtocolDecl *> RefedProtocols,
ArrayRef<ObjCPropertyDecl *> ClassProperties) {
WriteModernMetadataDeclarations(Result);
Result += "\nstatic struct _category_t ";
Result += "_OBJC_$_CATEGORY_";
Result += ClassName; Result += "_$_"; Result += CatName;
Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";
Result += "{\n";
Result += "\t\""; Result += ClassName; Result += "\",\n";
Result += "\t&"; Result += "OBJC_CLASS_$_"; Result += ClassName;
Result += ",\n";
if (InstanceMethods.size() > 0) {
Result += "\t(const struct _method_list_t *)&";
Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
Result += ClassName; Result += "_$_"; Result += CatName;
Result += ",\n";
}
else
Result += "\t0,\n";
if (ClassMethods.size() > 0) {
Result += "\t(const struct _method_list_t *)&";
Result += "_OBJC_$_CATEGORY_CLASS_METHODS_";
Result += ClassName; Result += "_$_"; Result += CatName;
Result += ",\n";
}
else
Result += "\t0,\n";
if (RefedProtocols.size() > 0) {
Result += "\t(const struct _protocol_list_t *)&";
Result += "_OBJC_CATEGORY_PROTOCOLS_$_";
Result += ClassName; Result += "_$_"; Result += CatName;
Result += ",\n";
}
else
Result += "\t0,\n";
if (ClassProperties.size() > 0) {
Result += "\t(const struct _prop_list_t *)&"; Result += "_OBJC_$_PROP_LIST_";
Result += ClassName; Result += "_$_"; Result += CatName;
Result += ",\n";
}
else
Result += "\t0,\n";
Result += "};\n";
}
static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj, static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj,
ASTContext *Context, std::string &Result, ASTContext *Context, std::string &Result,
ArrayRef<ObjCMethodDecl *> Methods, ArrayRef<ObjCMethodDecl *> Methods,
@ -6113,6 +6168,23 @@ void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {
} }
Result += "};\n"; Result += "};\n";
} }
if (CatDefCount > 0) {
Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ [";
Result += llvm::utostr(CatDefCount); Result += "]";
Result +=
" __attribute__((used, section (\"__DATA, __objc_catlist,"
"regular,no_dead_strip\")))= {\n";
for (int i = 0; i < CatDefCount; i++) {
Result += "\t&_OBJC_$_CATEGORY_";
Result +=
CategoryImplementation[i]->getClassInterface()->getNameAsString();
Result += "_$_";
Result += CategoryImplementation[i]->getNameAsString();
Result += ",\n";
}
Result += "};\n";
}
} }
/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category /// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
@ -6121,15 +6193,15 @@ void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
std::string &Result) { std::string &Result) {
ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
// Find category declaration for this implementation. // Find category declaration for this implementation.
ObjCCategoryDecl *CDecl; ObjCCategoryDecl *CDecl=0;
for (CDecl = ClassDecl->getCategoryList(); CDecl; for (CDecl = ClassDecl->getCategoryList(); CDecl;
CDecl = CDecl->getNextClassCategory()) CDecl = CDecl->getNextClassCategory())
if (CDecl->getIdentifier() == IDecl->getIdentifier()) if (CDecl->getIdentifier() == IDecl->getIdentifier())
break; break;
std::string FullCategoryName = ClassDecl->getNameAsString(); std::string FullCategoryName = ClassDecl->getNameAsString();
FullCategoryName += '_'; FullCategoryName += "_$_";
FullCategoryName += IDecl->getNameAsString(); FullCategoryName += CDecl->getNameAsString();
// Build _objc_method_list for class's instance methods if needed // Build _objc_method_list for class's instance methods if needed
SmallVector<ObjCMethodDecl *, 32> SmallVector<ObjCMethodDecl *, 32>
@ -6154,79 +6226,55 @@ void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
InstanceMethods.push_back(Setter); 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 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), "_OBJC_$_CATEGORY_INSTANCE_METHODS_",
false, "CATEGORY_", FullCategoryName.c_str(), FullCategoryName, true);
Result);
SmallVector<ObjCMethodDecl *, 32>
ClassMethods(IDecl->classmeth_begin(), IDecl->classmeth_end());
Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
"_OBJC_$_CATEGORY_CLASS_METHODS_",
FullCategoryName, true);
// Protocols referenced in class declaration? // Protocols referenced in class declaration?
// Null CDecl is case of a category implementation with no category interface // Protocol's super protocol list
if (CDecl) std::vector<ObjCProtocolDecl *> RefedProtocols;
RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY", const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols();
FullCategoryName, Result); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
/* struct _objc_category { E = Protocols.end();
char *category_name; I != E; ++I) {
char *class_name; RefedProtocols.push_back(*I);
struct _objc_method_list *instance_methods; // Must write out all protocol definitions in current qualifier list,
struct _objc_method_list *class_methods; // and in their nested qualifiers before writing out current definition.
struct _objc_protocol_list *protocols; RewriteObjCProtocolMetaData(*I, Result);
// 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; Write_protocol_list_initializer(Context, Result,
if (!objc_category) { RefedProtocols,
Result += "\nstruct _objc_category {\n"; "_OBJC_CATEGORY_PROTOCOLS_$_",
Result += "\tchar *category_name;\n"; FullCategoryName);
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()) { // Protocol's property metadata.
Result += "\t, (struct _objc_method_list *)" std::vector<ObjCPropertyDecl *> ClassProperties;
"&_OBJC_CATEGORY_INSTANCE_METHODS_"; for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
Result += FullCategoryName; E = CDecl->prop_end(); I != E; ++I)
Result += "\n"; ClassProperties.push_back(*I);
}
else Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,
Result += "\t, 0\n"; /* Container */0,
if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { "_OBJC_$_PROP_LIST_",
Result += "\t, (struct _objc_method_list *)" FullCategoryName);
"&_OBJC_CATEGORY_CLASS_METHODS_";
Result += FullCategoryName; Write_category_t(*this, Context, Result,
Result += "\n"; CDecl->getNameAsString(),
} ClassDecl->getNameAsString(),
else InstanceMethods,
Result += "\t, 0\n"; ClassMethods,
RefedProtocols,
ClassProperties);
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";
} }
// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or // RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or