On Thu, Apr 21, 2011 at 5:04 PM, Nathan Froyd <[email protected]> wrote:
> This patch does two things:
>
> - centralizes some infrastructure for defining builtin function types
> for frontends by providing a common function that
> DEF_FUNCTION_TYPE_FOO macros can call; and
>
> - in order to do that well, it also introduces
> build{,_varargs}_function_type_array for cases when
> build_function_type_list's interface doesn't work so well.
>
> build_function_type_list could have been used instead, but it would lose
> the error_mark_node handling provided in the C/C++/Ada/LTO frontends.
> This new interface will be necessary for eliminating other uses of
> build_function_type anyway.
>
> It would have been easier to move all of the builtin-types stuff into
> the middle-end, but Fortran doesn't use builtin-types.def. Even if it
> did, I suppose it's possible that some new front-end could have its own
> set of builtin types, so I'm leaving things as they are.
But this is what should be done, at least for all builtins in the
BUILT_IN_NORMAL category. ISTR Fortran was once running into
the issue of assigning different DECL_FUNCTION_CODE numbers to
those builtins than other languages, breaking LTO.
So, it would be indeed nice to have a central middle-end place to
instantiate those builtins and their required types. I'm not sure how
far we are from that and am too lazy to look right now ...
Richard.
> The new functions can eliminate some of the games that were played with
> the recent backend changes to use build_function_type_list; if this
> patch is approved, I'll make the (currently uncommitted) patches that
> could use build_function_type_array do so.
>
> Bootstrap and testing in progress on x86_64-unknown-linux-gnu. OK to
> commit if successful?
>
> -Nathan
>
> gcc/ada/
> * gcc-interface/utils.c (def_fn_type): Delete.
> (DEF_FUNCTION_TYPE_0, DEF_FUNCTION_TYPE_1): Change to use
> define_builtin_function_type.
> (DEF_FUNCTION_TYPE_2, DEF_FUNCTION_TYPE_3, DEF_FUNCTION_TYPE_4):
> (DEF_FUNCTION_TYPE_5, DEF_FUNCTION_TYPE_6, DEF_FUNCTION_TYPE_7):
> (DEF_FUNCTION_TYPE_VAR_0, DEF_FUNCTION_TYPE_VAR_1):
> (DEF_FUNCTION_TYPE_VAR_2, DEF_FUNCTION_TYPE_VAR_3):
> (DEF_FUNCTION_TYPE_VAR_4, DEF_FUNCTION_TYPE_VAR_5): Likewise.
>
> gcc/c-family/:
> * c-common.c (def_fn_type): Delete.
> (DEF_FUNCTION_TYPE_0, DEF_FUNCTION_TYPE_1): Change to use
> define_builtin_function_type.
> (DEF_FUNCTION_TYPE_2, DEF_FUNCTION_TYPE_3, DEF_FUNCTION_TYPE_4):
> (DEF_FUNCTION_TYPE_5, DEF_FUNCTION_TYPE_6, DEF_FUNCTION_TYPE_7):
> (DEF_FUNCTION_TYPE_VAR_0, DEF_FUNCTION_TYPE_VAR_1):
> (DEF_FUNCTION_TYPE_VAR_2, DEF_FUNCTION_TYPE_VAR_3):
> (DEF_FUNCTION_TYPE_VAR_4, DEF_FUNCTION_TYPE_VAR_5): Likewise.
>
> gcc/
> * tree.h (build_function_type_array): Declare.
> (build_varargs_function_type_array, define_builtin_function_type):
> Declare.
> * tree.c (build_function_type_array_1): Define.
> (build_function_type_array, build_varargs_function_type_array): Define.
> (define_builtin_function_type): Define.
>
> gcc/fortran/
> * f95-lang.c (DEF_FUNCTION_TYPE_0, DEF_FUNCTION_TYPE_1): Change
> to use define_builtin_function_type.
> (DEF_FUNCTION_TYPE_2, DEF_FUNCTION_TYPE_3, DEF_FUNCTION_TYPE_4):
> (DEF_FUNCTION_TYPE_5, DEF_FUNCTION_TYPE_6, DEF_FUNCTION_TYPE_7):
> (DEF_FUNCTION_TYPE_VAR_0): Likewise.
>
> gcc/lto/
> * lto-lang.c (def_fn_type): Delete.
> (DEF_FUNCTION_TYPE_0, DEF_FUNCTION_TYPE_1): Change to use
> define_builtin_function_type.
> (DEF_FUNCTION_TYPE_2, DEF_FUNCTION_TYPE_3, DEF_FUNCTION_TYPE_4):
> (DEF_FUNCTION_TYPE_5, DEF_FUNCTION_TYPE_6, DEF_FUNCTION_TYPE_7):
> (DEF_FUNCTION_TYPE_VAR_0, DEF_FUNCTION_TYPE_VAR_1):
> (DEF_FUNCTION_TYPE_VAR_2, DEF_FUNCTION_TYPE_VAR_3):
> (DEF_FUNCTION_TYPE_VAR_4, DEF_FUNCTION_TYPE_VAR_5): Likewise.
>
> diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
> index 1031ee9..6eb136d 100644
> --- a/gcc/ada/gcc-interface/utils.c
> +++ b/gcc/ada/gcc-interface/utils.c
> @@ -4952,47 +4952,6 @@ typedef enum c_builtin_type builtin_type;
> /* A temporary array used in communication with def_fn_type. */
> static GTY(()) tree builtin_types[(int) BT_LAST + 1];
>
> -/* A helper function for install_builtin_types. Build function type
> - for DEF with return type RET and N arguments. If VAR is true, then the
> - function should be variadic after those N arguments.
> -
> - Takes special care not to ICE if any of the types involved are
> - error_mark_node, which indicates that said type is not in fact available
> - (see builtin_type_for_size). In which case the function type as a whole
> - should be error_mark_node. */
> -
> -static void
> -def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
> -{
> - tree args = NULL, t;
> - va_list list;
> - int i;
> -
> - va_start (list, n);
> - for (i = 0; i < n; ++i)
> - {
> - builtin_type a = (builtin_type) va_arg (list, int);
> - t = builtin_types[a];
> - if (t == error_mark_node)
> - goto egress;
> - args = tree_cons (NULL_TREE, t, args);
> - }
> - va_end (list);
> -
> - args = nreverse (args);
> - if (!var)
> - args = chainon (args, void_list_node);
> -
> - t = builtin_types[ret];
> - if (t == error_mark_node)
> - goto egress;
> - t = build_function_type (t, args);
> -
> - egress:
> - builtin_types[def] = t;
> - va_end (list);
> -}
> -
> /* Build the builtin function types and install them in the builtin_types
> array for later use in builtin function decls. */
>
> @@ -5016,35 +4975,35 @@ install_builtin_function_types (void)
> #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
> builtin_types[ENUM] = VALUE;
> #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
> - def_fn_type (ENUM, RETURN, 0, 0);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 0);
> #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
> - def_fn_type (ENUM, RETURN, 0, 1, ARG1);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 1, (int) ARG1);
> #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
> - def_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 2, (int) ARG1, (int) ARG2);
> #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
> - def_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 3, (int) ARG1, (int) ARG2, (int) ARG3);
> #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
> - def_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 4, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4);
> #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)
> \
> - def_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 5, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5);
> #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
> ARG6) \
> - def_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 6, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5, (int)
> ARG6);
> #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
> ARG6, ARG7) \
> - def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 7, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5, (int)
> ARG6, (int) ARG7);
> #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
> - def_fn_type (ENUM, RETURN, 1, 0);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 0);
> #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
> - def_fn_type (ENUM, RETURN, 1, 1, ARG1);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 1, (int) ARG1);
> #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
> - def_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 2, (int) ARG1, (int) ARG2);
> #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
> - def_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 3, (int) ARG1, (int) ARG2, (int) ARG3);
> #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
> - def_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 4, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4);
> #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
> - def_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 5, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5);
> #define DEF_POINTER_TYPE(ENUM, TYPE) \
> builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]);
>
> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> index 752806e..b33630a 100644
> --- a/gcc/c-family/c-common.c
> +++ b/gcc/c-family/c-common.c
> @@ -4399,47 +4399,6 @@ typedef enum c_builtin_type builtin_type;
> communication with def_fn_type. */
> static tree builtin_types[(int) BT_LAST + 1];
>
> -/* A helper function for c_common_nodes_and_builtins. Build function type
> - for DEF with return type RET and N arguments. If VAR is true, then the
> - function should be variadic after those N arguments.
> -
> - Takes special care not to ICE if any of the types involved are
> - error_mark_node, which indicates that said type is not in fact available
> - (see builtin_type_for_size). In which case the function type as a whole
> - should be error_mark_node. */
> -
> -static void
> -def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
> -{
> - tree args = NULL, t;
> - va_list list;
> - int i;
> -
> - va_start (list, n);
> - for (i = 0; i < n; ++i)
> - {
> - builtin_type a = (builtin_type) va_arg (list, int);
> - t = builtin_types[a];
> - if (t == error_mark_node)
> - goto egress;
> - args = tree_cons (NULL_TREE, t, args);
> - }
> - va_end (list);
> -
> - args = nreverse (args);
> - if (!var)
> - args = chainon (args, void_list_node);
> -
> - t = builtin_types[ret];
> - if (t == error_mark_node)
> - goto egress;
> - t = build_function_type (t, args);
> -
> - egress:
> - builtin_types[def] = t;
> - va_end (list);
> -}
> -
> /* Build builtin functions common to both C and C++ language
> frontends. */
>
> @@ -4449,35 +4408,35 @@ c_define_builtins (tree va_list_ref_type_node, tree
> va_list_arg_type_node)
> #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
> builtin_types[ENUM] = VALUE;
> #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
> - def_fn_type (ENUM, RETURN, 0, 0);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 0);
> #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
> - def_fn_type (ENUM, RETURN, 0, 1, ARG1);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 1, (int) ARG1);
> #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
> - def_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 2, (int) ARG1, (int) ARG2);
> #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
> - def_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 3, (int) ARG1, (int) ARG2, (int) ARG3);
> #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
> - def_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 4, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4);
> #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)
> \
> - def_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 5, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5);
> #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
> ARG6) \
> - def_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 6, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5, (int)
> ARG6);
> #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
> ARG6, ARG7) \
> - def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 7, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5, (int)
> ARG6, (int) ARG7);
> #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
> - def_fn_type (ENUM, RETURN, 1, 0);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 0);
> #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
> - def_fn_type (ENUM, RETURN, 1, 1, ARG1);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 1, (int) ARG1);
> #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
> - def_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 2, (int) ARG1, (int) ARG2);
> #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
> - def_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 3, (int) ARG1, (int) ARG2, (int) ARG3);
> #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
> - def_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 4, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4);
> #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
> - def_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 5, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5);
> #define DEF_POINTER_TYPE(ENUM, TYPE) \
> builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]);
>
> diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
> index eb38484..71a5365 100644
> --- a/gcc/fortran/f95-lang.c
> +++ b/gcc/fortran/f95-lang.c
> @@ -1024,72 +1024,26 @@ gfc_init_builtin_functions (void)
>
> #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
> builtin_types[(int) ENUM] = VALUE;
> -#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
> - builtin_types[(int) ENUM] \
> - = build_function_type_list (builtin_types[(int) RETURN], \
> - NULL_TREE);
> -#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1)
> \
> - builtin_types[(int) ENUM] \
> - = build_function_type_list (builtin_types[(int) RETURN], \
> - builtin_types[(int) ARG1], \
> - NULL_TREE);
> -#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
> - builtin_types[(int) ENUM] \
> - = build_function_type_list (builtin_types[(int) RETURN], \
> - builtin_types[(int) ARG1], \
> - builtin_types[(int) ARG2], \
> - NULL_TREE);
> -#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
> - builtin_types[(int) ENUM] \
> - = build_function_type_list (builtin_types[(int) RETURN], \
> - builtin_types[(int) ARG1], \
> - builtin_types[(int) ARG2], \
> - builtin_types[(int) ARG3], \
> - NULL_TREE);
> -#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
> - builtin_types[(int) ENUM] \
> - = build_function_type_list (builtin_types[(int) RETURN], \
> - builtin_types[(int) ARG1], \
> - builtin_types[(int) ARG2], \
> - builtin_types[(int) ARG3], \
> - builtin_types[(int) ARG4], \
> - NULL_TREE);
> +#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 0);
> +#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 1, (int) ARG1);
> +#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 2, (int) ARG1, (int) ARG2);
> +#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 3, (int) ARG1, (int) ARG2, (int) ARG3);
> +#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 4, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4);
> #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)
> \
> - builtin_types[(int) ENUM] \
> - = build_function_type_list (builtin_types[(int) RETURN], \
> - builtin_types[(int) ARG1], \
> - builtin_types[(int) ARG2], \
> - builtin_types[(int) ARG3], \
> - builtin_types[(int) ARG4], \
> - builtin_types[(int) ARG5], \
> - NULL_TREE);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 5, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5);
> #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
> ARG6) \
> - builtin_types[(int) ENUM] \
> - = build_function_type_list (builtin_types[(int) RETURN], \
> - builtin_types[(int) ARG1], \
> - builtin_types[(int) ARG2], \
> - builtin_types[(int) ARG3], \
> - builtin_types[(int) ARG4], \
> - builtin_types[(int) ARG5], \
> - builtin_types[(int) ARG6], \
> - NULL_TREE);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 6, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5, (int)
> ARG6);
> #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
> ARG6, ARG7) \
> - builtin_types[(int) ENUM] \
> - = build_function_type_list (builtin_types[(int) RETURN], \
> - builtin_types[(int) ARG1], \
> - builtin_types[(int) ARG2], \
> - builtin_types[(int) ARG3], \
> - builtin_types[(int) ARG4], \
> - builtin_types[(int) ARG5], \
> - builtin_types[(int) ARG6], \
> - builtin_types[(int) ARG7], \
> - NULL_TREE);
> -#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
> - builtin_types[(int) ENUM] \
> - = build_varargs_function_type_list (builtin_types[(int) RETURN], \
> - NULL_TREE);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 7, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5, (int)
> ARG6, (int) ARG7);
> +#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 0);
> #define DEF_POINTER_TYPE(ENUM, TYPE) \
> builtin_types[(int) ENUM] \
> = build_pointer_type (builtin_types[(int) TYPE]);
> diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
> index c65d916..de2eb19 100644
> --- a/gcc/lto/lto-lang.c
> +++ b/gcc/lto/lto-lang.c
> @@ -428,40 +428,6 @@ handle_format_arg_attribute (tree * ARG_UNUSED (node),
> tree ARG_UNUSED (name),
> }
>
>
> -/* Cribbed from c-common.c. */
> -
> -static void
> -def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
> -{
> - tree args = NULL, t;
> - va_list list;
> - int i;
> -
> - va_start (list, n);
> - for (i = 0; i < n; ++i)
> - {
> - builtin_type a = (builtin_type) va_arg (list, int);
> - t = builtin_types[a];
> - if (t == error_mark_node)
> - goto egress;
> - args = tree_cons (NULL_TREE, t, args);
> - }
> - va_end (list);
> -
> - args = nreverse (args);
> - if (!var)
> - args = chainon (args, void_list_node);
> -
> - t = builtin_types[ret];
> - if (t == error_mark_node)
> - goto egress;
> - t = build_function_type (t, args);
> -
> - egress:
> - builtin_types[def] = t;
> - va_end (list);
> -}
> -
> /* Used to help initialize the builtin-types.def table. When a type of
> the correct size doesn't exist, use error_mark_node instead of NULL.
> The later results in segfaults even when a decl using the type doesn't
> @@ -539,35 +505,35 @@ lto_define_builtins (tree va_list_ref_type_node
> ATTRIBUTE_UNUSED,
> #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
> builtin_types[ENUM] = VALUE;
> #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
> - def_fn_type (ENUM, RETURN, 0, 0);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 0);
> #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
> - def_fn_type (ENUM, RETURN, 0, 1, ARG1);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 1, (int) ARG1);
> #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
> - def_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 2, (int) ARG1, (int) ARG2);
> #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
> - def_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 3, (int) ARG1, (int) ARG2, (int) ARG3);
> #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
> - def_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 4, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4);
> #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)
> \
> - def_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 5, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5);
> #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
> ARG6) \
> - def_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 6, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5, (int)
> ARG6);
> #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
> ARG6, ARG7) \
> - def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> false, 7, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5, (int)
> ARG6, (int) ARG7);
> #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
> - def_fn_type (ENUM, RETURN, 1, 0);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 0);
> #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
> - def_fn_type (ENUM, RETURN, 1, 1, ARG1);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 1, (int) ARG1);
> #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
> - def_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 2, (int) ARG1, (int) ARG2);
> #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
> - def_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 3, (int) ARG1, (int) ARG2, (int) ARG3);
> #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
> - def_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 4, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4);
> #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
> - def_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
> + define_builtin_function_type (builtin_types, (int) ENUM, (int) RETURN,
> true, 5, (int) ARG1, (int) ARG2, (int) ARG3, (int) ARG4, (int) ARG5);
> #define DEF_POINTER_TYPE(ENUM, TYPE) \
> builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]);
>
> diff --git a/gcc/tree.c b/gcc/tree.c
> index d0c18b1..008e6f7 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -7631,6 +7631,79 @@ build_varargs_function_type_list (tree return_type,
> ...)
> return args;
> }
>
> +/* Build a function type. RETURN_TYPE is the type returned by the
> + function; VAARGS indicates whether the function takes varargs. The
> + function takes N named arguments, the types of which are provided in
> + ARG_TYPES. */
> +
> +static tree
> +build_function_type_array_1 (bool vaargs, tree return_type, int n,
> + tree *arg_types)
> +{
> + int i;
> + tree t = vaargs ? NULL_TREE : void_list_node;
> +
> + for (i = n - 1; i >= 0; i--)
> + t = tree_cons (NULL_TREE, arg_types[i], t);
> +
> + return build_function_type (return_type, t);
> +}
> +
> +/* Build a function type. RETURN_TYPE is the type returned by the
> + function. The function takes N named arguments, the types of which
> + are provided in ARG_TYPES. */
> +
> +tree
> +build_function_type_array (tree return_type, int n, tree *arg_types)
> +{
> + return build_function_type_array_1 (false, return_type, n, arg_types);
> +}
> +
> +/* Build a variable argument function type. RETURN_TYPE is the type
> + returned by the function. The function takes N named arguments, the
> + types of which are provided in ARG_TYPES. */
> +
> +tree
> +build_varargs_function_type_array (tree return_type, int n, tree *arg_types)
> +{
> + return build_function_type_array_1 (true, return_type, n, arg_types);
> +}
> +
> +/* Build a function type and store it in BUILTIN_TYPES at FNTYPE_IDX.
> + RETURN_TYPE_IDX is the index of the return type of the function in
> + BUILTIN_TYPES. VAARGS indicates whether the function takes varargs.
> + The function takes N named arguments, of which indices into
> + BUILTIN_TYPES are provided as varargs. */
> +
> +void
> +define_builtin_function_type (tree *builtin_types, int fntype_idx,
> + int return_type_idx, bool vaargs,
> + int n, ...)
> +{
> + int i;
> + va_list list;
> + tree t, *arg_types = XALLOCAVEC (tree, n);
> +
> + va_start (list, n);
> + for (i = 0; i < n; i++)
> + {
> + int arg_type_idx = va_arg (list, int);
> + t = builtin_types[arg_type_idx];
> + if (t == error_mark_node)
> + goto egress;
> + arg_types[i] = t;
> + }
> +
> + t = builtin_types[return_type_idx];
> + if (t == error_mark_node)
> + goto egress;
> + t = build_function_type_array_1 (vaargs, t, n, arg_types);
> +
> + egress:
> + builtin_types[fntype_idx] = t;
> + va_end (list);
> +}
> +
> /* Build a METHOD_TYPE for a member of BASETYPE. The RETTYPE (a TYPE)
> and ARGTYPES (a TREE_LIST) are the return type and arguments types
> for the method. An implicit additional parameter (of type
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 0bc98cd..0e231e9 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -4252,6 +4252,9 @@ extern tree build_function_type_list (tree, ...);
> extern tree build_function_type_skip_args (tree, bitmap);
> extern tree build_function_decl_skip_args (tree, bitmap);
> extern tree build_varargs_function_type_list (tree, ...);
> +extern tree build_function_type_array (tree, int, tree *);
> +extern tree build_varargs_function_type_array (tree, int, tree *);
> +extern void define_builtin_function_type (tree *, int, int, bool, int, ...);
> extern tree build_method_type_directly (tree, tree, tree);
> extern tree build_method_type (tree, tree);
> extern tree build_offset_type (tree, tree);
>