Patchwork don't use build_function_type in the ObjC/C++ frontends

login
register
mail settings
Submitter Nathan Froyd
Date May 5, 2011, 3:17 a.m.
Message ID <20110505031752.GM23480@codesourcery.com>
Download mbox | patch
Permalink /patch/94197/
State New
Headers show

Comments

Nathan Froyd - May 5, 2011, 3:17 a.m.
The last remaining uses of build_function_type in the ObjC/C++ frontends
comes from this pattern:

  tree method_param_types =
    get_arg_type_list (method_prototype, METHOD_REF, super_flag);
  tree ftype = build_function_type (ret_type, method_param_types);

To eliminate this, I made the following changes:

- Package the above pattern up into a function,
  build_function_type_for_method.  This change meant that
  get_arg_type_list didn't need to exist as a separate function, so I
  made get_arg_type_list go away.

- To make build_function_type_for_method call build_function_type_vec, I
  needed to change the interface to the runtime hook function
  get_arg_type_list_base: it now takes a VEC to which it appends the
  necessary arguments.  build_function_type_for_method then appends the
  appropriate arguments and builds the new function type.

- However, the NeXT v2 ABI method call builder used the type list
  returned by get_arg_type_list separately, passing it to
  objc_copy_to_temp_side_effect_params.  I therefore changed that
  function to consult the newly built function type instead, using an
  iterator.

I also adjust the header comments to reflect the new world order and
wrapped them to < 80 columns where appropriate.

Tested on x86_64-unknown-linux-gnu, ObjC/C++ testsuites.  I will fix any
Darwin breakage that comes up, though I may need some debugging help to
do so.  OK to commit?

-Nathan

gcc/objc/
	* objc-runtime-shared-support.h (get_arg_type_list): Delete.
	(build_function_type_for_method): Declare.
	* objc-runtime-hooks.h (struct _objc_runtime_hooks_r): Change
	type of get_arg_type_base_list field.
	* objc-act.h (OBJC_VOID_AT_END): Delete.
	* objc-act.c (get_arg_type_list): Delete.
	(build_function_type_for_method): New function.
	(objc_decl_method_attributes): Call build_function_type_for_method.
	(really_start_method): Likewise.
	* objc-gnu-runtime-abi-01.c
	(gnu_runtime_abi_01_get_type_arg_list_base): Change prototype and
	adjust function accordingly.  Update header comment.
	(build_objc_method_call): Call build_function_type_for_method.
	* objc-next-runtime-abi-01.c
	(next_runtime_abi_01_get_type_arg_list_base): Change prototype and
	adjust function accordingly.  Update header comment.
	(build_objc_method_call): Call build_function_type_for_method.
	* objc-next-runtime-abi-02.c
	(next_runtime_abi_02_get_type_arg_list_base): Change prototype and
	adjust function accordingly.  Update header comment.
	(objc_copy_to_temp_side_effect_params): Take fntype instead of a
	typelist.  Use function_args_iterator for traversing fntype.
	(build_v2_build_objc_method_call): Adjust call to it.
	Call build_function_type_for_method
Mike Stump - May 5, 2011, 4:30 p.m.
On May 4, 2011, at 8:17 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> The last remaining uses of build_function_type in the ObjC/C++ frontends
> comes from this pattern:

>  OK to commit?

Ok.
>

Patch

diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 025f375..e3de6db 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -5040,8 +5040,9 @@  objc_decl_method_attributes (tree *node, tree attributes, int flags)
 	 (by setting TREE_DEPRECATED and TREE_THIS_VOLATILE) so there
 	 is nothing to do.  */
       tree saved_type = TREE_TYPE (*node);
-      TREE_TYPE (*node) = build_function_type
-	(TREE_VALUE (saved_type), get_arg_type_list (*node, METHOD_REF, 0));
+      TREE_TYPE (*node)
+	= build_function_type_for_method (TREE_VALUE (saved_type), *node,
+					  METHOD_REF, 0);
       decl_attributes (node, filtered_attributes, flags);
       METHOD_TYPE_ATTRIBUTES (*node) = TYPE_ATTRIBUTES (TREE_TYPE (*node));
       TREE_TYPE (*node) = saved_type;
@@ -5054,60 +5055,66 @@  objc_method_decl (enum tree_code opcode)
   return opcode == INSTANCE_METHOD_DECL || opcode == CLASS_METHOD_DECL;
 }
 
-/* Used by `build_objc_method_call'.  Return an argument list for
-   method METH.  CONTEXT is either METHOD_DEF or METHOD_REF, saying
-   whether we are trying to define a method or call one.  SUPERFLAG
-   says this is for a send to super; this makes a difference for the
-   NeXT calling sequence in which the lookup and the method call are
-   done together.  If METH is null, user-defined arguments (i.e.,
-   beyond self and _cmd) shall be represented by `...'.  */
+/* Return a function type for METHOD with RETURN_TYPE.  CONTEXT is
+   either METHOD_DEF or METHOD_REF, indicating whether we are defining a
+   method or calling one.  SUPER_FLAG indicates whether this is a send
+   to super; this makes a difference for the NeXT calling sequence in
+   which the lookup and the method call are done together.  If METHOD is
+   NULL, user-defined arguments (i.e., beyond self and _cmd) shall be
+   represented as varargs.  */
 
 tree
-get_arg_type_list (tree meth, int context, int superflag)
+build_function_type_for_method (tree return_type, tree method,
+				int context, bool super_flag)
 {
-  tree arglist, akey;
+  VEC(tree,gc) *argtypes = make_tree_vector ();
+  tree t, ftype;
+  bool is_varargs = false;
 
-  /* Receiver & _cmd types are runtime-dependent.  */
-  arglist = (*runtime.get_arg_type_list_base) (meth, context, superflag);
+  (*runtime.get_arg_type_list_base) (&argtypes, method, context, super_flag);
 
-  /* No actual method prototype given -- assume that remaining arguments
-     are `...'.  */
-  if (!meth)
-    return arglist;
+  /* No actual method prototype given; remaining args passed as varargs.  */
+  if (method == NULL_TREE)
+    {
+      is_varargs = true;
+      goto build_ftype;
+    }
 
-  /* Build a list of argument types.  */
-  for (akey = METHOD_SEL_ARGS (meth); akey; akey = DECL_CHAIN (akey))
+  for (t = METHOD_SEL_ARGS (method); t; t = DECL_CHAIN (t))
     {
-      tree arg_type = TREE_VALUE (TREE_TYPE (akey));
+      tree arg_type = TREE_VALUE (TREE_TYPE (t));
 
-      /* Decay argument types for the underlying C function as appropriate.  */
+      /* Decay argument types for the underlying C function as
+         appropriate.  */
       arg_type = objc_decay_parm_type (arg_type);
 
-      chainon (arglist, build_tree_list (NULL_TREE, arg_type));
+      VEC_safe_push (tree, gc, argtypes, arg_type);
     }
 
-  if (METHOD_ADD_ARGS (meth))
+  if (METHOD_ADD_ARGS (method))
     {
-      for (akey = TREE_CHAIN (METHOD_ADD_ARGS (meth));
-	   akey; akey = TREE_CHAIN (akey))
+      for (t = TREE_CHAIN (METHOD_ADD_ARGS (method));
+	   t; t = TREE_CHAIN (t))
 	{
-	  tree arg_type = TREE_TYPE (TREE_VALUE (akey));
+	  tree arg_type = TREE_TYPE (TREE_VALUE (t));
 
 	  arg_type = objc_decay_parm_type (arg_type);
 
-	  chainon (arglist, build_tree_list (NULL_TREE, arg_type));
+	  VEC_safe_push (tree, gc, argtypes, arg_type);
 	}
 
-      if (!METHOD_ADD_ARGS_ELLIPSIS_P (meth))
-	goto lack_of_ellipsis;
+      if (METHOD_ADD_ARGS_ELLIPSIS_P (method))
+	is_varargs = true;
     }
+
+ build_ftype:
+  if (is_varargs)
+    ftype = build_varargs_function_type_vec (return_type, argtypes);
   else
-    {
-     lack_of_ellipsis:
-      chainon (arglist, OBJC_VOID_AT_END);
-    }
+    ftype = build_function_type_vec (return_type, argtypes);
 
-  return arglist;
+  release_tree_vector (argtypes);
+  return ftype;
 }
 
 static tree
@@ -8692,9 +8699,7 @@  really_start_method (tree method,
   push_lang_context (lang_name_c);
 #endif
 
-  meth_type
-    = build_function_type (ret_type,
-			   get_arg_type_list (method, METHOD_DEF, 0));
+  meth_type = build_function_type_for_method (ret_type, method, METHOD_DEF, 0);
   objc_start_function (method_id, meth_type, NULL_TREE, parmlist);
 
   /* Set self_decl from the first argument.  */
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 30c74c5..d31bb7d 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -665,8 +665,6 @@  typedef enum string_section
 #define OBJC_MODIFIER_TRANSIENT		0x00000200
 #define OBJC_MODIFIER_NONE_SPECIFIED	0x80000000
 
-#define OBJC_VOID_AT_END		void_list_node
-
 /* Exception handling constructs.  We begin by having the parser do most
    of the work and passing us blocks.
    This allows us to handle different exceptions implementations.  */
diff --git a/gcc/objc/objc-gnu-runtime-abi-01.c b/gcc/objc/objc-gnu-runtime-abi-01.c
index fdeebea..efd8ad1 100644
--- a/gcc/objc/objc-gnu-runtime-abi-01.c
+++ b/gcc/objc/objc-gnu-runtime-abi-01.c
@@ -103,7 +103,8 @@  static tree gnu_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry
 static tree gnu_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
 
 static tree gnu_runtime_abi_01_receiver_is_class_object (tree);
-static tree gnu_runtime_abi_01_get_arg_type_list_base (tree, int, int);
+static void gnu_runtime_abi_01_get_arg_type_list_base (VEC(tree,gc) **, tree,
+						       int, int);
 static tree gnu_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
 							tree, tree, tree, int);
 
@@ -577,27 +578,28 @@  gnu_runtime_abi_01_get_class_reference (tree ident)
   return build_function_call (input_location, objc_get_class_decl, params);
 }
 
-/* Used by get_arg_type_list.
-   Return the types for receiver & _cmd at the start of a method argument list.
-   context is either METHOD_DEF or METHOD_REF, saying whether we are trying
-   to define a method or call one.  superflag says this is for a send to super.
-   meth may be NULL, in the case that there is no prototype.  */
+/* Used by build_function_type_for_method.  Append the types for
+   receiver & _cmd at the start of a method argument list to ARGTYPES.
+   CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
+   trying to define a method or call one.  SUPERFLAG says this is for a
+   send to super.  METH may be NULL, in the case that there is no
+   prototype.  */
 
-static tree
-gnu_runtime_abi_01_get_arg_type_list_base (tree meth, int context,
+static void
+gnu_runtime_abi_01_get_arg_type_list_base (VEC(tree,gc) **argtypes, tree meth,
+					   int context,
 					   int superflag ATTRIBUTE_UNUSED)
 {
-  tree arglist;
+  tree receiver_type;
 
-  /* Receiver type.  */
   if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
-    arglist = build_tree_list (NULL_TREE, objc_instance_type);
+    receiver_type = objc_instance_type;
   else
-    arglist = build_tree_list (NULL_TREE, objc_object_type);
+    receiver_type = objc_object_type;
 
+  VEC_safe_push (tree, gc, *argtypes, receiver_type);
   /* Selector type - will eventually change to `int'.  */
-  chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
-  return arglist;
+  VEC_safe_push (tree, gc, *argtypes, objc_selector_type);
 }
 
 /* Unused for GNU runtime.  */
@@ -672,10 +674,9 @@  build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
     = (method_prototype
        ? TREE_VALUE (TREE_TYPE (method_prototype))
        : objc_object_type);
-
-  tree method_param_types =
-    get_arg_type_list (method_prototype, METHOD_REF, super_flag);
-  tree ftype = build_function_type (ret_type, method_param_types);
+  tree ftype
+    = build_function_type_for_method (ret_type, method_prototype,
+				      METHOD_REF, super_flag);
   tree sender_cast;
   tree method, t;
 
diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c
index 4fb2a38..d5b795f 100644
--- a/gcc/objc/objc-next-runtime-abi-01.c
+++ b/gcc/objc/objc-next-runtime-abi-01.c
@@ -123,7 +123,8 @@  static tree next_runtime_abi_01_get_class_super_ref (location_t, struct imp_entr
 static tree next_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
 
 static tree next_runtime_abi_01_receiver_is_class_object (tree);
-static tree next_runtime_abi_01_get_arg_type_list_base (tree, int, int);
+static void next_runtime_abi_01_get_arg_type_list_base (VEC(tree,gc) **, tree,
+							int, int);
 static tree next_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
 							tree, tree, tree, int);
 static bool next_runtime_abi_01_setup_const_string_class_decl (void);
@@ -721,28 +722,29 @@  next_runtime_abi_01_get_class_reference (tree ident)
     }
 }
 
-/* Used by get_arg_type_list.
-   Return the types for receiver & _cmd at the start of a method argument list.
-   context is either METHOD_DEF or METHOD_REF, saying whether we are trying
-   to define a method or call one.  superflag says this is for a send to super.
-   meth may be NULL, in the case that there is no prototype.  */
+/* Used by build_function_type_for_method.  Append the types for
+   receiver & _cmd at the start of a method argument list to ARGTYPES.
+   CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
+   trying to define a method or call one.  SUPERFLAG says this is for a
+   send to super.  METH may be NULL, in the case that there is no
+   prototype.  */
 
-static tree
-next_runtime_abi_01_get_arg_type_list_base (tree meth, int context, int superflag)
+static void
+next_runtime_abi_01_get_arg_type_list_base (VEC(tree,gc) **argtypes, tree meth,
+					    int context, int superflag)
 {
-  tree arglist;
+  tree receiver_type;
 
-  /* Receiver type.  */
   if (superflag)
-    arglist = build_tree_list (NULL_TREE, objc_super_type);
+    receiver_type = objc_super_type;
   else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
-    arglist = build_tree_list (NULL_TREE, objc_instance_type);
+    receiver_type = objc_instance_type;
   else
-    arglist = build_tree_list (NULL_TREE, objc_object_type);
+    receiver_type = objc_object_type;
 
+  VEC_safe_push (tree, gc, *argtypes, receiver_type);
   /* Selector type - will eventually change to `int'.  */
-  chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
-  return arglist;
+  VEC_safe_push (tree, gc, *argtypes, objc_selector_type);
 }
 
 static tree
@@ -828,10 +830,8 @@  build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
     = (method_prototype
        ? TREE_VALUE (TREE_TYPE (method_prototype))
        : objc_object_type);
-
-  tree method_param_types =
-    get_arg_type_list (method_prototype, METHOD_REF, super_flag);
-  tree ftype = build_function_type (ret_type, method_param_types);
+  tree ftype = build_function_type_for_method (ret_type, method_prototype,
+					       METHOD_REF, super_flag);
 
   if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
     ftype = build_type_attribute_variant (ftype,
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index 90660d7..3d889b0 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -213,7 +213,8 @@  static tree next_runtime_abi_02_get_class_super_ref (location_t, struct imp_entr
 static tree next_runtime_abi_02_get_category_super_ref (location_t, struct imp_entry *, bool);
 
 static tree next_runtime_abi_02_receiver_is_class_object (tree);
-static tree next_runtime_abi_02_get_arg_type_list_base (tree, int, int);
+static void next_runtime_abi_02_get_arg_type_list_base (VEC(tree,gc) **, tree,
+							int, int);
 static tree next_runtime_abi_02_build_objc_method_call (location_t, tree, tree,
 							tree, tree, tree, int);
 static bool next_runtime_abi_02_setup_const_string_class_decl (void);
@@ -1098,31 +1099,32 @@  next_runtime_abi_02_get_class_reference (tree ident)
     }
 }
 
-/* Used by get_arg_type_list.
-   Return the types for receiver & _cmd at the start of a method
-   argument list.  context is either METHOD_DEF or METHOD_REF, saying
-   whether we are trying to define a method or call one.  superflag
-   says this is for a send to super.  meth may be NULL, in the case
-   that there is no prototype.  */
+/* Used by build_function_type_for_method.  Append the types for
+   receiver & _cmd at the start of a method argument list to ARGTYPES.
+   CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
+   trying to define a method or call one.  SUPERFLAG says this is for a
+   send to super.  METH may be NULL, in the case that there is no
+   prototype.  */
 
-static tree
-next_runtime_abi_02_get_arg_type_list_base (tree meth, int context, int superflag)
+static void
+next_runtime_abi_02_get_arg_type_list_base (VEC(tree,gc) **argtypes, tree meth,
+					    int context, int superflag)
 {
-  tree arglist;
+  tree receiver_type;
 
-  /* Receiver type.  */
   if (superflag)
-    arglist = build_tree_list (NULL_TREE, objc_super_type);
+    receiver_type = objc_super_type;
   else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
-    arglist = build_tree_list (NULL_TREE, objc_instance_type);
+    receiver_type = objc_instance_type;
   else
-    arglist = build_tree_list (NULL_TREE, objc_object_type);
+    receiver_type = objc_object_type;
 
+  VEC_safe_push (tree, gc, *argtypes, receiver_type);
   /* Selector type - will eventually change to `int'.  */
-  chainon (arglist, build_tree_list (NULL_TREE,
-				     (superflag ? objc_v2_super_selector_type
-						: objc_v2_selector_type)));
-  return arglist;
+  VEC_safe_push (tree, gc, *argtypes,
+		 (superflag
+		  ? objc_v2_super_selector_type
+		  : objc_v2_selector_type));
 }
 
 /* TODO: Merge this with the message refs.  */
@@ -1539,23 +1541,26 @@  next_runtime_abi_02_receiver_is_class_object (tree receiver)
   return NULL_TREE;
 }
 
-/* Assign all arguments in VALUES which have side-effect to a
-   temporary and replaced that argument in VALUES list with the
-   temporary. TYPELIST is the list of argument types. */
+/* Assign all arguments in VALUES which have side-effect to a temporary
+   and replaced that argument in VALUES list with the temporary. The
+   arguments will be passed to a function with FNTYPE.  */
 
 static tree
-objc_copy_to_temp_side_effect_params (tree typelist, tree values)
+objc_copy_to_temp_side_effect_params (tree fntype, tree values)
 {
-  tree valtail, typetail;
+  tree valtail;
+  function_args_iterator iter;
+
   /* Skip over receiver and the &_msf_ref types.  */
-  gcc_assert (TREE_CHAIN (typelist));
-  typetail = TREE_CHAIN (TREE_CHAIN (typelist));
+  function_args_iter_init (&iter, fntype);
+  function_args_iter_next (&iter);
+  function_args_iter_next (&iter);
 
   for (valtail = values; valtail;
-       valtail = TREE_CHAIN (valtail), typetail = TREE_CHAIN (typetail))
+       valtail = TREE_CHAIN (valtail), function_args_iter_next (&iter))
     {
       tree value = TREE_VALUE (valtail);
-      tree type = typetail ? TREE_VALUE (typetail) : NULL_TREE;
+      tree type = function_args_iter_cond (&iter);
       if (type == NULL_TREE)
 	break;
       if (!TREE_SIDE_EFFECTS (value))
@@ -1583,10 +1588,8 @@  build_v2_build_objc_method_call (int super_flag, tree method_prototype,
     = (method_prototype
        ? TREE_VALUE (TREE_TYPE (method_prototype))
        : objc_object_type);
-  tree method_param_types = get_arg_type_list (method_prototype,
+  tree ftype = build_function_type_for_method (ret_type, method_prototype,
 					       METHOD_REF, super_flag);
-
-  tree ftype = build_function_type (ret_type, method_param_types);
   tree sender_cast;
 
   if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
@@ -1596,7 +1599,7 @@  build_v2_build_objc_method_call (int super_flag, tree method_prototype,
   sender_cast = build_pointer_type (ftype);
 
   if (check_for_nil)
-    method_params = objc_copy_to_temp_side_effect_params (method_param_types,
+    method_params = objc_copy_to_temp_side_effect_params (ftype,
 							  method_params);
 
   /* Get &message_ref_t.messenger.  */
diff --git a/gcc/objc/objc-runtime-hooks.h b/gcc/objc/objc-runtime-hooks.h
index d2606ff..9145681 100644
--- a/gcc/objc/objc-runtime-hooks.h
+++ b/gcc/objc/objc-runtime-hooks.h
@@ -75,7 +75,7 @@  typedef struct _objc_runtime_hooks_r
   /* Receiver is class Object, check runtime-specific.  */
   tree (*receiver_is_class_object) (tree);
   /* Get the start of a method argument type list (receiver, _cmd).  */
-  tree (*get_arg_type_list_base) (tree, int, int);
+  void (*get_arg_type_list_base) (VEC(tree,gc) **, tree, int, int);
   /* Build method call.  */
   tree (*build_objc_method_call) (location_t, tree, tree, tree, tree, tree, int);
 
diff --git a/gcc/objc/objc-runtime-shared-support.h b/gcc/objc/objc-runtime-shared-support.h
index ace9039..5646bfa 100644
--- a/gcc/objc/objc-runtime-shared-support.h
+++ b/gcc/objc/objc-runtime-shared-support.h
@@ -49,7 +49,8 @@  extern void objc_start_function (tree, tree, tree, struct c_arg_info *);
 extern struct c_arg_info *objc_get_parm_info (int);
 #endif
 extern void objc_push_parm (tree);
-extern tree get_arg_type_list (tree, int, int);
+
+extern tree build_function_type_for_method (tree, tree, int, bool);
 
 /* Stuff that should be migrated to shared support (or some v1-only file).  */
 extern void build_super_template (void);