Patchwork centralize builtin function type building

login
register
mail settings
Submitter Nathan Froyd
Date April 21, 2011, 3:04 p.m.
Message ID <20110421150445.GA2039@nightcrawler>
Download mbox | patch
Permalink /patch/92421/
State New
Headers show

Comments

Nathan Froyd - April 21, 2011, 3:04 p.m.
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.

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.
Richard Guenther - April 21, 2011, 3:36 p.m.
On Thu, Apr 21, 2011 at 5:04 PM, Nathan Froyd <froydnj@codesourcery.com> 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);
>
Michael Meissner - April 21, 2011, 7:15 p.m.
On Thu, Apr 21, 2011 at 05:36:42PM +0200, Richard Guenther wrote:
> On Thu, Apr 21, 2011 at 5:04 PM, Nathan Froyd <froydnj@codesourcery.com> 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 ...

I agree that it is desirable that the backend builtin index not overlap with
the standard builtin index (and front end builtin index).  I was starting to
look at this, when I learned Kenneth Zadeck was working on a more comprehensive
solution for backend builtin types.  Obviously all 3 of our efforts should be
merged into one goal.
Nathan Froyd - April 22, 2011, 3:55 p.m.
On Thu, Apr 21, 2011 at 05:36:42PM +0200, Richard Guenther wrote:
> On Thu, Apr 21, 2011 at 5:04 PM, Nathan Froyd <froydnj@codesourcery.com> 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.
> >
> > 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 ...

I agree that it would be better to have a central middle-end place for
this; I'm not entirely sure why Fortran opts to use a separate set of
types; AFAICS, it's a strict subset.  Fortran folks...?

The question of decls is something different and unrelated to this
patch, IMHO.  Is the patch OK as-is, or should I work on merging the
types into the middle-end in addition?

-Nathan

Patch

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);