diff mbox series

[pushed] Objective-C, Darwin : Update protocol metadata to current version.

Message ID 2E01B100-D4FB-48DE-9374-7D99E1C3C7AE@sandoe.co.uk
State New
Headers show
Series [pushed] Objective-C, Darwin : Update protocol metadata to current version. | expand

Commit Message

Iain Sandoe Oct. 11, 2020, 10:31 a.m. UTC
Hi

Later versions of the NeXT runtime protocol metadata contain additional
fields.  This patch adds these fields and populates a new list of
method types.

tested across the range of supported Darwin systems, and on x86_64-linux
pushed to master,
thanks
Iain

gcc/objc/ChangeLog:

	* objc-next-runtime-abi-02.c (build_v2_super_template): Add new
	fields to the template.
	(build_v2_protocol_template): Build new field entries.
	(generate_v2_meth_descriptor_table): Adjust to allow recording all
	method types.
	(generate_v2_meth_type_list): New.
	(build_v2_protocol_initializer): Initialize the additional fields.
	(generate_v2_protocols): Record method types for all entries and
	generate the additional method type table.
---
 gcc/objc/objc-next-runtime-abi-02.c | 103 +++++++++++++++++++++++-----
 1 file changed, 87 insertions(+), 16 deletions(-)
diff mbox series

Patch

diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index 57604255065..3a308975325 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -743,6 +743,9 @@  build_v2_super_template (void)
      const struct _prop_list_t * const properties;
      const uint32_t size;
      const uint32_t flags;
+     const char ** extended_method_types;
+     const char * demangled_name;
+     const struct _prop_list_t * class_properties;
    }
 */
 static void
@@ -784,6 +787,16 @@  build_v2_protocol_template (void)
   /* const uint32_t flags; */
   add_field_decl (integer_type_node, "flags", &chain);
 
+  /* const char **extendedMethodTypes; */
+  tree ptr_to_ptr_to_char = build_pointer_type (string_type_node);
+  add_field_decl (ptr_to_ptr_to_char, "extended_method_types", &chain);
+
+  /* const char *demangledName; */
+  add_field_decl (string_type_node, "demangled_name", &chain);
+
+  /* const struct _prop_list_t *class_properties; */
+  add_field_decl (objc_prop_list_ptr, "class_properties", &chain);
+
   objc_finish_struct (objc_v2_protocol_template, decls);
 }
 
@@ -2296,9 +2309,10 @@  build_v2_method_list_template (tree list_type, int size)
    objc_method_prototype_template which is missing this field.  */
 static tree
 generate_v2_meth_descriptor_table (tree chain, tree protocol,
-				   const char *prefix, tree attr)
+				   const char *prefix, tree attr,
+				   vec<tree>& all_meths)
 {
-  tree method_list_template, initlist, decl, methods;
+  tree method_list_template, initlist, decl;
   int size, entsize;
   vec<constructor_elt, va_gc> *v = NULL;
   char buf[BUFSIZE];
@@ -2306,13 +2320,14 @@  generate_v2_meth_descriptor_table (tree chain, tree protocol,
   if (!chain || !prefix)
     return NULL_TREE;
 
-  methods = chain;
+  tree method = chain;
   size = 0;
-  while (methods)
+  while (method)
     {
-      if (! METHOD_ENCODING (methods))
-	METHOD_ENCODING (methods) = encode_method_prototype (methods);
-      methods = TREE_CHAIN (methods);
+      if (! METHOD_ENCODING (method))
+	METHOD_ENCODING (method) = encode_method_prototype (method);
+      all_meths.safe_push (method);
+      method = TREE_CHAIN (method);
       size++;
     }
 
@@ -2337,6 +2352,31 @@  generate_v2_meth_descriptor_table (tree chain, tree protocol,
   return decl;
 }
 
+static tree
+generate_v2_meth_type_list (vec<tree>& all_meths, tree protocol,
+			    const char *prefix)
+{
+  if (all_meths.is_empty () || !prefix)
+    return NULL_TREE;
+
+  unsigned size = all_meths.length ();
+  tree list_type = build_sized_array_type (string_type_node, size);
+  char *nam;
+  asprintf (&nam, "%s_%s", prefix,
+	    IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
+  tree decl = start_var_decl (list_type, nam);
+  free (nam);
+  OBJCMETA (decl, objc_meta, meta_base);
+  vec<constructor_elt, va_gc> *v = NULL;
+
+  for (unsigned i = 0; i < size; ++i)
+    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+			    add_objc_string (METHOD_ENCODING (all_meths[i]),
+					     meth_var_types));
+  finish_var_decl (decl, objc_build_constructor (list_type, v));
+  return decl;
+}
+
 /* This routine builds the initializer list to initialize the 'struct
    _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data.  */
 
@@ -2463,7 +2503,8 @@  static tree
 build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
 			      tree inst_methods, tree class_methods,
 			      tree opt_ins_meth, tree opt_cls_meth,
-			      tree property_list)
+			      tree property_list, tree ext_meth_types,
+			      tree demangled_name, tree class_prop_list)
 {
   tree expr, ttyp;
   location_t loc;
@@ -2518,7 +2559,28 @@  build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list
   /* const uint32_t flags; = 0 */
   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
 
-  return objc_build_constructor (type, inits);
+  ttyp = build_pointer_type (string_type_node);
+  if (ext_meth_types)
+    expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, ext_meth_types, 0));
+  else
+    expr = convert (ttyp, null_pointer_node);
+  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+  ttyp = string_type_node;
+   if (demangled_name)
+    expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, demangled_name, 0));
+  else
+    expr = convert (ttyp, null_pointer_node);
+  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+  ttyp = objc_prop_list_ptr;
+   if (class_prop_list)
+    expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_prop_list, 0));
+  else
+    expr = convert (ttyp, null_pointer_node);
+  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+ return objc_build_constructor (type, inits);
 }
 
 /* Main routine to build all meta data for all protocols used in a
@@ -2554,25 +2616,26 @@  generate_v2_protocols (void)
       loc = DECL_SOURCE_LOCATION (decl);
       some = true;
 
+      vec<tree> all_meths = vNULL;
       inst_meth =
 	generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
 					   "_OBJC_ProtocolInstanceMethods",
-					   meta_proto_nst_meth);
+					   meta_proto_nst_meth, all_meths);
 
       class_meth =
 	generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
 					   "_OBJC_ProtocolClassMethods",
-					   meta_proto_cls_meth);
+					   meta_proto_cls_meth, all_meths);
 
       opt_inst_meth =
 	generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
-					   "_OBJC_OptProtocolInstMethods",
-					   meta_proto_nst_meth);
+					   "_OBJC_ProtocolOptInstMethods",
+					   meta_proto_nst_meth, all_meths);
 
       opt_class_meth =
 	generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
-					   "_OBJC_OptProtocolClassMethods",
-					   meta_proto_cls_meth);
+					   "_OBJC_ProtocolOptClassMethods",
+					   meta_proto_cls_meth, all_meths);
 
       if (PROTOCOL_LIST (p))
 	refs_decl = generate_v2_protocol_list (p, NULL_TREE);
@@ -2590,13 +2653,21 @@  generate_v2_protocols (void)
 
       props = generate_v2_property_table (p, NULL_TREE);
 
+      tree ext_meth_types
+	= generate_v2_meth_type_list (all_meths, p,
+				      "_OBJC_ProtocolMethodTypes");
+      tree demangled_name = NULL_TREE;
+      tree class_prop_list = NULL_TREE;
+
       initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
 						protocol_name_expr, refs_expr,
 						inst_meth, class_meth,
 						opt_inst_meth, opt_class_meth,
-						props);
+						props, ext_meth_types,
+						demangled_name,class_prop_list);
       finish_var_decl (decl, initlist);
       objc_add_to_protocol_list (p, decl);
+      all_meths.truncate (0);
     }
 
   if (some)