[JAVA] Overhaul Java front-end's builtin handling.

Roger Sayle roger@eyesopen.com
Sat May 31 16:47:00 GMT 2003


The following patch fulfils my promise to Andrew Haley to reorganize
the java front-end's handling of GCC builtins.  This patch also
happily deletes the notorious hacks required to re-use builtins.def
which were worthy of mention in Zack's developer conference presentation.

Instead of struggling to re-use builtins.def, gcj now defines only
the builtins that it requires manually, using a mechanism similar to
that used by the fortran front-end in f/com.c.  This switch allows
the added functionality of specifying the java.lang.Math functions in
libgcj as the fallback routines, rather than fallback to libc, which
may potentially have accuracy issues.

Indeed this change means that java.lang.Math.sqrt should now correctly
throw a java.lang.Arithmetic exception with its argument is negative.
It also reduces java/builtins.c by over a thousand lines.


There are still a number of middle-end improvements/fixes that I'd
like to make in this area, however this patch has the dual advantages
of restricting itself to the java front-end and being a significant
improvement on what's currently there.  Patches for the remaining
issues, I'll submit to separately and shouldn't require java approval.


The following patch has been tested on i686-pc-linux-gnu with a
complete bootstrap, all languages except treelang, and regression
tested with a top-level "make -k check" with no new failures.
[No changes are required to java/Make-lang.in: builtins.def wasn't
previously listed as an explicit dependency of builtins.o].

Ok for mainline?


2003-05-31  Roger Sayle  <roger@eyesopen.com>

	* builtins.c (define_builtin_type, builtin_types): Delete.
	(define_builtin): Rewritten to take just the built-in code,
	the function's name, type and fallback library function name.
	All built-ins used by Java are implicit and BUILT_IN_NORMAL.
	(initialize_builtins): Overhaul to define the GCC builtins
	used by gcj manually, providing the Java run-time's
	implementations as the fallback library function.

	* libjava.lang/MathBuiltin.java: New test case.
	* libjava.lang/MathBuiltin.out: New file.


Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/builtins.c,v
retrieving revision 1.18
diff -c -3 -p -r1.18 builtins.c
*** builtins.c	29 May 2003 16:38:04 -0000	1.18
--- builtins.c	31 May 2003 05:39:09 -0000
*************** static tree abs_builtin (tree, tree);
*** 69,76 ****

  static tree java_build_function_call_expr (tree, tree);
  static void define_builtin (enum built_in_function, const char *,
! 			    enum built_in_class, tree, int, int);
! static tree define_builtin_type (int, int, int, int, int);



--- 69,75 ----

  static tree java_build_function_call_expr (tree, tree);
  static void define_builtin (enum built_in_function, const char *,
! 			    tree, const char *);



*************** static GTY(()) struct builtin_record jav
*** 114,123 ****
    { { NULL }, { NULL }, NULL, END_BUILTINS }
  };

- /* This is only used transiently, so we don't mark it as roots for the
-    GC.  */
- static tree builtin_types[(int) BT_LAST];
-

  /* Internal functions which implement various builtin conversions.  */

--- 113,118 ----
*************** java_build_function_call_expr (tree fn,
*** 163,232 ****
  static void
  define_builtin (enum built_in_function val,
  		const char *name,
- 		enum built_in_class class,
  		tree type,
! 		int fallback_p,
! 		int implicit)
  {
    tree decl;

-   if (! name || ! type)
-     return;
-
-   if (strncmp (name, "__builtin_", strlen ("__builtin_")) != 0)
-     abort ();
    decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
    DECL_EXTERNAL (decl) = 1;
    TREE_PUBLIC (decl) = 1;
!   if (fallback_p)
!     SET_DECL_ASSEMBLER_NAME (decl,
! 			     get_identifier (name + strlen ("__builtin_")));
    make_decl_rtl (decl, NULL);
    pushdecl (decl);
!   DECL_BUILT_IN_CLASS (decl) = class;
    DECL_FUNCTION_CODE (decl) = val;
-   built_in_decls[val] = decl;
-   if (implicit)
-     implicit_built_in_decls[val] = decl;
- }
-
- /* Compute the type for a builtin.  */
- static tree
- define_builtin_type (int ret, int arg1, int arg2, int arg3, int arg4)
- {
-   tree args;
-
-   if (builtin_types[ret] == NULL_TREE)
-     return NULL_TREE;
-
-   args = void_list_node;

!   if (arg4 != -1)
!     {
!       if (builtin_types[arg4] == NULL_TREE)
! 	return NULL_TREE;
!       args = tree_cons (NULL_TREE, builtin_types[arg4], args);
!     }
!   if (arg3 != -1)
!     {
!       if (builtin_types[arg3] == NULL_TREE)
! 	return NULL_TREE;
!       args = tree_cons (NULL_TREE, builtin_types[arg3], args);
!     }
!   if (arg2 != -1)
!     {
!       if (builtin_types[arg2] == NULL_TREE)
! 	return NULL_TREE;
!       args = tree_cons (NULL_TREE, builtin_types[arg2], args);
!     }
!   if (arg1 != -1)
!     {
!       if (builtin_types[arg1] == NULL_TREE)
! 	return NULL_TREE;
!       args = tree_cons (NULL_TREE, builtin_types[arg1], args);
!     }
!
!   return build_function_type (builtin_types[ret], args);
  }


--- 158,179 ----
  static void
  define_builtin (enum built_in_function val,
  		const char *name,
  		tree type,
! 		const char *libname)
  {
    tree decl;

    decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
    DECL_EXTERNAL (decl) = 1;
    TREE_PUBLIC (decl) = 1;
!   SET_DECL_ASSEMBLER_NAME (decl, get_identifier (libname));
    make_decl_rtl (decl, NULL);
    pushdecl (decl);
!   DECL_BUILT_IN_CLASS (decl) = BUILT_IN_NORMAL;
    DECL_FUNCTION_CODE (decl) = val;

!   implicit_built_in_decls[val] = decl;
!   built_in_decls[val] = decl;
  }


*************** define_builtin_type (int ret, int arg1,
*** 235,240 ****
--- 182,190 ----
  void
  initialize_builtins (void)
  {
+   tree double_ftype_double, double_ftype_double_double;
+   tree float_ftype_float, float_ftype_float_float;
+   tree t;
    int i;

    for (i = 0; java_builtins[i].builtin_code != END_BUILTINS; ++i)
*************** initialize_builtins (void)
*** 248,295 ****

    void_list_node = end_params_node;

!   /* Work around C-specific junk in builtin-types.def.  */
! #define intmax_type_node NULL_TREE
! #define c_size_type_node NULL_TREE
! #define const_string_type_node NULL_TREE
! #define va_list_ref_type_node NULL_TREE
! #define va_list_arg_type_node NULL_TREE
! #define flag_isoc99 0
!
! #define DEF_PRIMITIVE_TYPE(ENUM, VALUE)					      \
!   builtin_types[(int) ENUM] = VALUE;
! #define DEF_FUNCTION_TYPE_0(ENUM, RETURN)		\
!   builtin_types[(int) ENUM]				\
!     = define_builtin_type (RETURN, -1, -1, -1, -1);
! #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1)				\
!   builtin_types[(int) ENUM]						\
!     = define_builtin_type (RETURN, ARG1, -1, -1, -1);
! #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2)	\
!   builtin_types[(int) ENUM]				\
!     = define_builtin_type (RETURN, ARG1, ARG2, -1, -1);
! #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3)		 \
!   builtin_types[(int) ENUM]						 \
!     = define_builtin_type (RETURN, ARG1, ARG2, ARG3, -1);
! #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4)	\
!   builtin_types[(int) ENUM]						\
!     = define_builtin_type (RETURN, ARG1, ARG2, ARG3, ARG4);
! #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN)			\
!   builtin_types[(int) ENUM] = NULL_TREE;
! #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1)		\
!    builtin_types[(int) ENUM] = NULL_TREE;
! #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2)	\
!    builtin_types[(int) ENUM] = NULL_TREE;
! #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3)	\
!    builtin_types[(int) ENUM] = NULL_TREE;
! #define DEF_POINTER_TYPE(ENUM, TYPE)			\
!   builtin_types[(int) ENUM] = NULL_TREE;
!
! #include "builtin-types.def"
!
! #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, \
!                     FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT) \
!   define_builtin (ENUM, NAME, CLASS, builtin_types[TYPE], FALLBACK_P, IMPLICIT);
! #include "builtins.def"
  }

  /* If the call matches a builtin, return the
--- 198,236 ----

    void_list_node = end_params_node;

!   t = tree_cons (NULL_TREE, float_type_node, end_params_node);
!   float_ftype_float = build_function_type (float_type_node, t);
!   t = tree_cons (NULL_TREE, float_type_node, t);
!   float_ftype_float_float = build_function_type (float_type_node, t);
!
!   t = tree_cons (NULL_TREE, double_type_node, end_params_node);
!   double_ftype_double = build_function_type (double_type_node, t);
!   t = tree_cons (NULL_TREE, double_type_node, t);
!   double_ftype_double_double = build_function_type (double_type_node, t);
!
!   define_builtin (BUILT_IN_FMOD, "__builtin_fmod",
! 		  double_ftype_double_double, "fmod");
!   define_builtin (BUILT_IN_FMODF, "__builtin_fmodf",
! 		  float_ftype_float_float, "fmodf");
!
!   define_builtin (BUILT_IN_ATAN, "__builtin_atan",
! 		  double_ftype_double, "_ZN4java4lang4Math4atanEd");
!   define_builtin (BUILT_IN_ATAN2, "__builtin_atan2",
! 		  double_ftype_double_double, "_ZN4java4lang4Math5atan2Edd");
!   define_builtin (BUILT_IN_COS, "__builtin_cos",
! 		  double_ftype_double, "_ZN4java4lang4Math3cosEd");
!   define_builtin (BUILT_IN_EXP, "__builtin_exp",
! 		  double_ftype_double, "_ZN4java4lang4Math3expEd");
!   define_builtin (BUILT_IN_LOG, "__builtin_log",
! 		  double_ftype_double, "_ZN4java4lang4Math3logEd");
!   define_builtin (BUILT_IN_POW, "__builtin_pow",
! 		  double_ftype_double_double, "_ZN4java4lang4Math3powEdd");
!   define_builtin (BUILT_IN_SIN, "__builtin_sin",
! 		  double_ftype_double, "_ZN4java4lang4Math3sinEd");
!   define_builtin (BUILT_IN_SQRT, "__builtin_sqrt",
! 		  double_ftype_double, "_ZN4java4lang4Math4sqrtEd");
!   define_builtin (BUILT_IN_TAN, "__builtin_tan",
! 		  double_ftype_double, "_ZN4java4lang4Math3tanEd");
  }

  /* If the call matches a builtin, return the


class MathBuiltin
{
  static double abs(double x)
  {
    return Math.abs(x);
  }

  static double atan(double x)
  {
    return Math.atan(x);
  }

  static double atan2(double x, double y)
  {
    return Math.atan2(x,y);
  }

  static double cos(double x)
  {
    return Math.cos(x);
  }

  static double exp(double x)
  {
    return Math.exp(x);
  }

  static double log(double x)
  {
    return Math.log(x);
  }

  static double max(double x, double y)
  {
    return Math.max(x,y);
  }

  static double min(double x, double y)
  {
    return Math.min(x,y);
  }

  static double pow(double x, double y)
  {
    return Math.pow(x,y);
  }

  static double sin(double x)
  {
    return Math.sin(x);
  }

  static double sqrt(double x)
  {
    return Math.sqrt(x);
  }

  static double tan(double x)
  {
    return Math.tan(x);
  }

  public static void main(String argv[])
  {
    double sum = abs (1.0) + atan (1.0) + atan2 (1.0, 1.0) + cos (1.0)
                 + exp (1.0) + log(1.0) + max(1.0, 1.0) + min (1.0, 1.0)
		 + pow (1.0, 1.0) + sin (1.0) + sqrt(1.0) + tan(1.0);
  }
}


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833



More information about the Java-patches mailing list