From patchwork Thu May 5 03:17:52 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Froyd X-Patchwork-Id: 94197 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 89608B6F1A for ; Thu, 5 May 2011 13:18:25 +1000 (EST) Received: (qmail 12077 invoked by alias); 5 May 2011 03:18:20 -0000 Received: (qmail 12012 invoked by uid 22791); 5 May 2011 03:18:11 -0000 X-SWARE-Spam-Status: No, hits=-1.6 required=5.0 tests=AWL, BAYES_00, TW_BJ, TW_FN, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 05 May 2011 03:17:54 +0000 Received: (qmail 30199 invoked from network); 5 May 2011 03:17:53 -0000 Received: from unknown (HELO localhost) (froydnj@127.0.0.2) by mail.codesourcery.com with ESMTPA; 5 May 2011 03:17:53 -0000 Date: Wed, 4 May 2011 20:17:52 -0700 From: Nathan Froyd To: gcc-patches@gcc.gnu.org Subject: [PATCH] don't use build_function_type in the ObjC/C++ frontends Message-ID: <20110505031752.GM23480@codesourcery.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.17+20080114 (2008-01-14) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 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);