summaryrefslogtreecommitdiff
path: root/gcc/java/builtins.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2002-01-22 20:23:46 +0000
committerTom Tromey <tromey@gcc.gnu.org>2002-01-22 20:23:46 +0000
commitfec763fcfdaad01e5ebb8ca1d3ccee34ef65f099 (patch)
tree38b316a8ea04383d07bdceb8943a04f07e0917cc /gcc/java/builtins.c
parent9ce3f7e5d3e94dbe814dbe1d2212064cb9084014 (diff)
downloadgcc-fec763fcfdaad01e5ebb8ca1d3ccee34ef65f099.tar.gz
decl.c (java_init_decl_processing): Use add_predefined_file.
* decl.c (java_init_decl_processing): Use add_predefined_file. Predefine RawData.java. (predef_filenames): Removed. (java_init_decl_processing): Don't register predef_filenames. * jcf-parse.c (add_predefined_file): New function. (predefined_filename_p): Rewrote. (predefined_filename_p): No longer static. * decl.c (java_init_decl_processing): Call initialize_builtins. * Make-lang.in (JAVA_OBJS): Added builtins.o. (java/builtins.o): New target. * builtins.c: New file. * parse.y (patch_invoke): Use build_call_or_builtin. * java-tree.h (build_call_or_builtin): Declare. (initialize_builtins): Declare. (java_set_exception_lang_code): Removed unused declaration. (PREDEF_FILENAMES_SIZE): Removed. (java_tree_index): Added JTI_PREDEF_FILENAMES. (predef_filenames): New define. (add_predefined_file): Declare. (predefined_filename_p): Declare. * expr.c (expand_invoke): Use build_call_or_builtin. From-SVN: r49091
Diffstat (limited to 'gcc/java/builtins.c')
-rw-r--r--gcc/java/builtins.c365
1 files changed, 365 insertions, 0 deletions
diff --git a/gcc/java/builtins.c b/gcc/java/builtins.c
new file mode 100644
index 00000000000..24498596375
--- /dev/null
+++ b/gcc/java/builtins.c
@@ -0,0 +1,365 @@
+/* Built-in and inline functions for gcj
+ Copyright (C) 2001
+ Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+Java and all Java-based marks are trademarks or registered trademarks
+of Sun Microsystems, Inc. in the United States and other countries.
+The Free Software Foundation is independent of Sun Microsystems, Inc. */
+
+/* Written by Tom Tromey <tromey@redhat.com>. */
+
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "ggc.h"
+#include "flags.h"
+
+#include "java-tree.h"
+
+enum builtin_type
+{
+#define DEF_PRIMITIVE_TYPE(NAME, VALUE) NAME,
+#define DEF_FUNCTION_TYPE_0(NAME, RETURN) NAME,
+#define DEF_FUNCTION_TYPE_1(NAME, RETURN, ARG1) NAME,
+#define DEF_FUNCTION_TYPE_2(NAME, RETURN, ARG1, ARG2) NAME,
+#define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
+#define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
+#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
+#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
+#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
+#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
+#include "builtin-types.def"
+#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_0
+#undef DEF_FUNCTION_TYPE_1
+#undef DEF_FUNCTION_TYPE_2
+#undef DEF_FUNCTION_TYPE_3
+#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_VAR_0
+#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_POINTER_TYPE
+ BT_LAST
+};
+
+static tree max_builtin PARAMS ((tree, tree));
+static tree min_builtin PARAMS ((tree, tree));
+static tree abs_builtin PARAMS ((tree, tree));
+static tree cos_builtin PARAMS ((tree, tree));
+static tree sin_builtin PARAMS ((tree, tree));
+static tree sqrt_builtin PARAMS ((tree, tree));
+
+static tree build_function_call_expr PARAMS ((tree, tree));
+static void define_builtin PARAMS ((enum built_in_function,
+ const char *,
+ enum built_in_class,
+ tree, int));
+static tree define_builtin_type PARAMS ((int, int, int, int, int));
+
+
+
+/* Functions of this type are used to inline a given call. Such a
+ function should either return an expression, if the call is to be
+ inlined, or NULL_TREE if a real call should be emitted. Arguments
+ are method return type and arguments to call. */
+typedef tree builtin_creator_function PARAMS ((tree, tree));
+
+/* Hold a char*, before initialization, or a tree, after
+ initialization. */
+union string_or_tree
+{
+ const char *s;
+ tree t;
+};
+
+/* Used to hold a single builtin record. */
+struct builtin_record
+{
+ union string_or_tree class_name;
+ union string_or_tree method_name;
+ builtin_creator_function *creator;
+};
+
+static struct builtin_record java_builtins[] =
+{
+ { { "java.lang.Math" }, { "min" }, min_builtin },
+ { { "java.lang.Math" }, { "max" }, max_builtin },
+ { { "java.lang.Math" }, { "abs" }, abs_builtin },
+ { { "java.lang.Math" }, { "cos" }, cos_builtin },
+ { { "java.lang.Math" }, { "sin" }, sin_builtin },
+ { { "java.lang.Math" }, { "sqrt" }, sqrt_builtin },
+ { { NULL }, { NULL }, NULL }
+};
+
+/* 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. */
+
+static tree
+max_builtin (method_return_type, method_arguments)
+ tree method_return_type, method_arguments;
+{
+ return build (MAX_EXPR, method_return_type,
+ TREE_VALUE (method_arguments),
+ TREE_VALUE (TREE_CHAIN (method_arguments)));
+}
+
+static tree
+min_builtin (method_return_type, method_arguments)
+ tree method_return_type, method_arguments;
+{
+ return build (MIN_EXPR, method_return_type,
+ TREE_VALUE (method_arguments),
+ TREE_VALUE (TREE_CHAIN (method_arguments)));
+}
+
+static tree
+abs_builtin (method_return_type, method_arguments)
+ tree method_return_type, method_arguments;
+{
+ return build1 (ABS_EXPR, method_return_type,
+ TREE_VALUE (method_arguments));
+}
+
+/* Mostly copied from ../builtins.c. */
+static tree
+build_function_call_expr (tree fn, tree arglist)
+{
+ tree call_expr;
+
+ call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
+ call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+ call_expr, arglist);
+ TREE_SIDE_EFFECTS (call_expr) = 1;
+ return call_expr;
+}
+
+static tree
+cos_builtin (method_return_type, method_arguments)
+ tree method_return_type, method_arguments;
+{
+ /* FIXME: this assumes that jdouble and double are the same. */
+ tree fn = built_in_decls[BUILT_IN_COS];
+ if (fn == NULL_TREE)
+ return NULL_TREE;
+ return build_function_call_expr (fn, method_arguments);
+}
+
+static tree
+sin_builtin (method_return_type, method_arguments)
+ tree method_return_type, method_arguments;
+{
+ /* FIXME: this assumes that jdouble and double are the same. */
+ tree fn = built_in_decls[BUILT_IN_SIN];
+ if (fn == NULL_TREE)
+ return NULL_TREE;
+ return build_function_call_expr (fn, method_arguments);
+}
+
+static tree
+sqrt_builtin (method_return_type, method_arguments)
+ tree method_return_type, method_arguments;
+{
+ /* FIXME: this assumes that jdouble and double are the same. */
+ tree fn = built_in_decls[BUILT_IN_SQRTF];
+ if (fn == NULL_TREE)
+ return NULL_TREE;
+ return build_function_call_expr (fn, method_arguments);
+}
+
+
+
+/* Define a single builtin. */
+static void
+define_builtin (val, name, class, type, fallback_p)
+ enum built_in_function val;
+ const char *name;
+ enum built_in_class class;
+ tree type;
+ int fallback_p;
+{
+ tree decl;
+
+ if (! name)
+ 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;
+}
+
+/* Compute the type for a builtin. */
+static tree
+define_builtin_type (ret, arg1, arg2, arg3, arg4)
+ int ret, arg1, arg2, arg3, 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);
+}
+
+
+
+/* Initialize the builtins. */
+void
+initialize_builtins ()
+{
+ int i;
+
+ for (i = 0; java_builtins[i].creator != NULL; ++i)
+ {
+ tree klass_id = get_identifier (java_builtins[i].class_name.s);
+ tree m = get_identifier (java_builtins[i].method_name.s);
+
+ java_builtins[i].class_name.t = klass_id;
+ java_builtins[i].method_name.t = m;
+ ggc_add_tree_root (&java_builtins[i].class_name.t, 1);
+ ggc_add_tree_root (&java_builtins[i].method_name.t, 1);
+ }
+
+ void_list_node = end_params_node;
+
+ /* Work around C-specific junk in builtin-types.def. */
+#define intmax_type_node NULL_TREE
+#define traditional_ptr_type_node NULL_TREE
+#define traditional_cptr_type_node NULL_TREE
+#define c_size_type_node NULL_TREE
+#define const_string_type_node NULL_TREE
+#define traditional_len_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_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) \
+ define_builtin (ENUM, NAME, CLASS, builtin_types[TYPE], FALLBACK_P);
+#include "builtins.def"
+}
+
+/* Generate a method call. If the call matches a builtin, return the
+ appropriate builtin expression instead. */
+tree
+build_call_or_builtin (method, func, method_arguments)
+ tree method, func, method_arguments;
+{
+ tree method_class = DECL_NAME (TYPE_NAME (DECL_CONTEXT (method)));
+ tree method_name = DECL_NAME (method);
+ tree method_return_type = TREE_TYPE (TREE_TYPE (method));
+ tree call = NULL_TREE;
+
+ /* Only look if we're generating object code and optimizing. */
+ if (! flag_emit_class_files && optimize)
+ {
+ int i;
+
+ for (i = 0; java_builtins[i].creator != NULL; ++i)
+ {
+ if (method_class == java_builtins[i].class_name.t
+ && method_name == java_builtins[i].method_name.t)
+ {
+ call = (*java_builtins[i].creator) (method_return_type,
+ method_arguments);
+ break;
+ }
+ }
+ }
+
+ if (call == NULL_TREE)
+ {
+ /* Either nothing matched, or the creator function decided not
+ to inline. In either case, emit a call. */
+ call = build (CALL_EXPR, method_return_type, func, method_arguments,
+ NULL_TREE);
+ TREE_SIDE_EFFECTS (call) = 1;
+ }
+
+ return call;
+}