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";
}
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,
ASTContext *Context, std::string &Result,
ArrayRef<ObjCMethodDecl *> Methods,
@ -6113,6 +6168,23 @@ void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {
}
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
@ -6121,15 +6193,15 @@ void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
std::string &Result) {
ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
// Find category declaration for this implementation.
ObjCCategoryDecl *CDecl;
ObjCCategoryDecl *CDecl=0;
for (CDecl = ClassDecl->getCategoryList(); CDecl;
CDecl = CDecl->getNextClassCategory())
if (CDecl->getIdentifier() == IDecl->getIdentifier())
break;
std::string FullCategoryName = ClassDecl->getNameAsString();
FullCategoryName += '_';
FullCategoryName += IDecl->getNameAsString();
FullCategoryName += "_$_";
FullCategoryName += CDecl->getNameAsString();
// Build _objc_method_list for class's instance methods if needed
SmallVector<ObjCMethodDecl *, 32>
@ -6154,79 +6226,55 @@ void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
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);
Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
"_OBJC_$_CATEGORY_INSTANCE_METHODS_",
FullCategoryName, true);
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?
// 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.
};
*/
// Protocol's super protocol list
std::vector<ObjCProtocolDecl *> RefedProtocols;
const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I) {
RefedProtocols.push_back(*I);
// Must write out all protocol definitions in current qualifier list,
// and in their nested qualifiers before writing out current definition.
RewriteObjCProtocolMetaData(*I, Result);
}
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";
Write_protocol_list_initializer(Context, Result,
RefedProtocols,
"_OBJC_CATEGORY_PROTOCOLS_$_",
FullCategoryName);
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";
// Protocol's property metadata.
std::vector<ObjCPropertyDecl *> ClassProperties;
for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
E = CDecl->prop_end(); I != E; ++I)
ClassProperties.push_back(*I);
Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,
/* Container */0,
"_OBJC_$_PROP_LIST_",
FullCategoryName);
Write_category_t(*this, Context, Result,
CDecl->getNameAsString(),
ClassDecl->getNameAsString(),
InstanceMethods,
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