]> granicus.if.org Git - clang/commitdiff
objc rewriter: modern metadata for protocol decls. wip.
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 7 Feb 2012 20:15:08 +0000 (20:15 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 7 Feb 2012 20:15:08 +0000 (20:15 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150002 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Rewrite/RewriteModernObjC.cpp

index 2e84db749e1451c4d56a982020ca69b0f00c1332..a2599f264e6fe2888f623453c7814b4b16291906 100644 (file)
@@ -5191,7 +5191,7 @@ void RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
 
 /// struct _objc_method {
 ///   SEL _cmd;
-///   char *method_type;
+///   const char *method_type;
 ///   char *_imp;
 /// }
 
@@ -5241,15 +5241,9 @@ static void WriteModernMetadataDeclarations(std::string &Result) {
   
   Result += "\nstruct _objc_method {\n";
   Result += "\tstruct objc_selector * _cmd;\n";
-  Result += "\tchar *method_type;\n";
+  Result += "\tconst char *method_type;\n";
   Result += "\tchar *_imp;\n";
   Result += "};\n";
-
-  Result += "\nstruct _method_list_t {\n";
-  Result += "\tunsigned int entsize;  // sizeof(struct _objc_method)\n";
-  Result += "\tunsigned int method_count;\n";
-  Result += "\tstruct _objc_method method_list[/*method_count*/];\n";
-  Result += "};\n";
   
   Result += "\nstruct _protocol_t {\n";
   Result += "\tvoid * isa;  // NULL\n";
@@ -5268,6 +5262,50 @@ static void WriteModernMetadataDeclarations(std::string &Result) {
   meta_data_declared = true;
 }
 
+static void Write_method_list_t_TypeDecl(std::string &Result,
+                                         unsigned int method_count) {
+  Result += "struct /*_method_list_t*/"; Result += " {\n";
+  Result += "\tunsigned int entsize;  // sizeof(struct _objc_method)\n";
+  Result += "\tunsigned int method_count;\n";
+  Result += "\tstruct _objc_method method_list[";
+  Result += utostr(method_count); Result += "];\n";
+  Result += "}";
+}
+
+static void Write_method_list_t_initializer(ASTContext *Context, std::string &Result,
+                                            ArrayRef<ObjCMethodDecl *> Methods,
+                                            StringRef VarName,
+                                            StringRef ProtocolName) {
+  if (Methods.size() > 0) {
+    Result += "\nstatic ";
+    Write_method_list_t_TypeDecl(Result, Methods.size());
+    Result += " "; Result += VarName;
+    Result += ProtocolName; 
+    Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
+    Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n";
+    Result += "\t"; Result += utostr(Methods.size()); Result += ",\n";
+    for (unsigned i = 0, e = Methods.size(); i < e; i++) {
+      ObjCMethodDecl *MD = Methods[i];
+      if (i == 0)
+        Result += "\t{{(struct objc_selector *)\"";
+      else
+        Result += "\t{(struct objc_selector *)\"";
+      Result += (MD)->getSelector().getAsString(); Result += "\"";
+      Result += ", ";
+      std::string MethodTypeString;
+      Context->getObjCEncodingForMethodDecl(MD, MethodTypeString);
+      Result += "\""; Result += MethodTypeString; Result += "\"";
+      Result += ", ";
+      // FIXME is _imp always null here?
+      if (i  == e-1)
+        Result += "0}}\n";
+      else
+        Result += "0},\n";
+    }
+    Result += "};\n";
+  }
+}
+
 /// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
 void RewriteModernObjC::RewriteObjCProtocolMetaData(
                             ObjCProtocolDecl *PDecl, StringRef prefix,
@@ -5297,6 +5335,48 @@ void RewriteModernObjC::RewriteObjCProtocolMetaData(
   if (ObjCProtocolDecl *Def = PDecl->getDefinition())
     PDecl = Def;
   
+  // Construct method lists.
+  std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods;
+  std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods;
+  for (ObjCProtocolDecl::instmeth_iterator
+       I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
+       I != E; ++I) {
+    ObjCMethodDecl *MD = *I;
+    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
+      OptInstanceMethods.push_back(MD);
+    } else {
+      InstanceMethods.push_back(MD);
+    }
+  }
+  
+  for (ObjCProtocolDecl::classmeth_iterator
+       I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
+       I != E; ++I) {
+    ObjCMethodDecl *MD = *I;
+    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
+      OptClassMethods.push_back(MD);
+    } else {
+      ClassMethods.push_back(MD);
+    }
+  }
+  Write_method_list_t_initializer(Context, Result, InstanceMethods, 
+                                  "_OBJC_PROTOCOL_INSTANCE_METHODS_",
+                                  PDecl->getNameAsString());
+  
+  Write_method_list_t_initializer(Context, Result, ClassMethods, 
+                                  "_OBJC_PROTOCOL_CLASS_METHODS_",
+                                  PDecl->getNameAsString());
+
+  Write_method_list_t_initializer(Context, Result, OptInstanceMethods, 
+                                  "_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_",
+                                  PDecl->getNameAsString());
+  
+  Write_method_list_t_initializer(Context, Result, OptClassMethods, 
+                                  "_OBJC_PROTOCOL_OPT_CLASS_METHODS_",
+                                  PDecl->getNameAsString());
+  
+  
+  // ====================================Legacy ABI ====================================================
   if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
     unsigned NumMethods = std::distance(PDecl->instmeth_begin(),
                                         PDecl->instmeth_end());