diff options
Diffstat (limited to 'gcc/java/builtins.c')
-rw-r--r-- | gcc/java/builtins.c | 641 |
1 files changed, 641 insertions, 0 deletions
diff --git a/gcc/java/builtins.c b/gcc/java/builtins.c new file mode 100644 index 000000000..2100f093a --- /dev/null +++ b/gcc/java/builtins.c @@ -0,0 +1,641 @@ +/* Built-in and inline functions for gcj + Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, 2009, 2010 + Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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 3, or (at your option) +any later version. + +GCC 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. + +. + +. + +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>. */ + +/* FIXME: Still need to include rtl.h here (see below). */ +#undef IN_GCC_FRONTEND + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "ggc.h" +#include "flags.h" +#include "langhooks.h" +#include "java-tree.h" + +/* FIXME: All these headers are necessary for sync_compare_and_swap. + Front ends should never have to look at that. */ +#include "rtl.h" +#include "insn-codes.h" +#include "expr.h" +#include "optabs.h" + +static tree max_builtin (tree, tree); +static tree min_builtin (tree, tree); +static tree abs_builtin (tree, tree); +static tree convert_real (tree, tree); + +static tree java_build_function_call_expr (tree, tree); + +static tree putObject_builtin (tree, tree); +static tree compareAndSwapInt_builtin (tree, tree); +static tree compareAndSwapLong_builtin (tree, tree); +static tree compareAndSwapObject_builtin (tree, tree); +static tree putVolatile_builtin (tree, tree); +static tree getVolatile_builtin (tree, tree); +static tree VMSupportsCS8_builtin (tree, tree); + + +/* 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 the original CALL_EXPR containing the + arguments to the call. */ +typedef tree builtin_creator_function (tree, tree); + +/* Hold a char*, before initialization, or a tree, after + initialization. */ +union GTY(()) string_or_tree { + const char * GTY ((tag ("0"))) s; + tree GTY ((tag ("1"))) t; +}; + +/* Used to hold a single builtin record. */ +struct GTY(()) builtin_record { + union string_or_tree GTY ((desc ("1"))) class_name; + union string_or_tree GTY ((desc ("1"))) method_name; + builtin_creator_function * GTY((skip)) creator; + enum built_in_function builtin_code; +}; + +static GTY(()) struct builtin_record java_builtins[] = +{ + { { "java.lang.Math" }, { "min" }, min_builtin, (enum built_in_function) 0 }, + { { "java.lang.Math" }, { "max" }, max_builtin, (enum built_in_function) 0 }, + { { "java.lang.Math" }, { "abs" }, abs_builtin, (enum built_in_function) 0 }, + { { "java.lang.Math" }, { "acos" }, NULL, BUILT_IN_ACOS }, + { { "java.lang.Math" }, { "asin" }, NULL, BUILT_IN_ASIN }, + { { "java.lang.Math" }, { "atan" }, NULL, BUILT_IN_ATAN }, + { { "java.lang.Math" }, { "atan2" }, NULL, BUILT_IN_ATAN2 }, + { { "java.lang.Math" }, { "ceil" }, NULL, BUILT_IN_CEIL }, + { { "java.lang.Math" }, { "cos" }, NULL, BUILT_IN_COS }, + { { "java.lang.Math" }, { "exp" }, NULL, BUILT_IN_EXP }, + { { "java.lang.Math" }, { "floor" }, NULL, BUILT_IN_FLOOR }, + { { "java.lang.Math" }, { "log" }, NULL, BUILT_IN_LOG }, + { { "java.lang.Math" }, { "pow" }, NULL, BUILT_IN_POW }, + { { "java.lang.Math" }, { "sin" }, NULL, BUILT_IN_SIN }, + { { "java.lang.Math" }, { "sqrt" }, NULL, BUILT_IN_SQRT }, + { { "java.lang.Math" }, { "tan" }, NULL, BUILT_IN_TAN }, + { { "java.lang.Float" }, { "intBitsToFloat" }, convert_real, + (enum built_in_function) 0 }, + { { "java.lang.Double" }, { "longBitsToDouble" }, convert_real, + (enum built_in_function) 0 }, + { { "java.lang.Float" }, { "floatToRawIntBits" }, convert_real, + (enum built_in_function) 0 }, + { { "java.lang.Double" }, { "doubleToRawLongBits" }, convert_real, + (enum built_in_function) 0 }, + { { "sun.misc.Unsafe" }, { "putInt" }, putObject_builtin, + (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "putLong" }, putObject_builtin, + (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "putObject" }, putObject_builtin, + (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "compareAndSwapInt" }, + compareAndSwapInt_builtin, (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "compareAndSwapLong" }, + compareAndSwapLong_builtin, (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "compareAndSwapObject" }, + compareAndSwapObject_builtin, (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "putOrderedInt" }, putVolatile_builtin, + (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "putOrderedLong" }, putVolatile_builtin, + (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "putOrderedObject" }, putVolatile_builtin, + (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "putIntVolatile" }, putVolatile_builtin, + (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "putLongVolatile" }, putVolatile_builtin, + (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "putObjectVolatile" }, putVolatile_builtin, + (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "getObjectVolatile" }, getVolatile_builtin, + (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "getIntVolatile" }, getVolatile_builtin, + (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "getLongVolatile" }, getVolatile_builtin, (enum built_in_function) 0}, + { { "sun.misc.Unsafe" }, { "getLong" }, getVolatile_builtin, + (enum built_in_function) 0}, + { { "java.util.concurrent.atomic.AtomicLong" }, { "VMSupportsCS8" }, + VMSupportsCS8_builtin, (enum built_in_function) 0}, + { { NULL }, { NULL }, NULL, END_BUILTINS } +}; + + +/* Internal functions which implement various builtin conversions. */ + +static tree +max_builtin (tree method_return_type, tree orig_call) +{ + /* MAX_EXPR does not handle -0.0 in the Java style. */ + if (TREE_CODE (method_return_type) == REAL_TYPE) + return NULL_TREE; + return fold_build2 (MAX_EXPR, method_return_type, + CALL_EXPR_ARG (orig_call, 0), + CALL_EXPR_ARG (orig_call, 1)); +} + +static tree +min_builtin (tree method_return_type, tree orig_call) +{ + /* MIN_EXPR does not handle -0.0 in the Java style. */ + if (TREE_CODE (method_return_type) == REAL_TYPE) + return NULL_TREE; + return fold_build2 (MIN_EXPR, method_return_type, + CALL_EXPR_ARG (orig_call, 0), + CALL_EXPR_ARG (orig_call, 1)); +} + +static tree +abs_builtin (tree method_return_type, tree orig_call) +{ + return fold_build1 (ABS_EXPR, method_return_type, + CALL_EXPR_ARG (orig_call, 0)); +} + +/* Construct a new call to FN using the arguments from ORIG_CALL. */ + +static tree +java_build_function_call_expr (tree fn, tree orig_call) +{ + int nargs = call_expr_nargs (orig_call); + switch (nargs) + { + /* Although we could handle the 0-3 argument cases using the general + logic in the default case, splitting them out permits folding to + be performed without constructing a temporary CALL_EXPR. */ + case 0: + return build_call_expr (fn, 0); + case 1: + return build_call_expr (fn, 1, CALL_EXPR_ARG (orig_call, 0)); + case 2: + return build_call_expr (fn, 2, + CALL_EXPR_ARG (orig_call, 0), + CALL_EXPR_ARG (orig_call, 1)); + case 3: + return build_call_expr (fn, 3, + CALL_EXPR_ARG (orig_call, 0), + CALL_EXPR_ARG (orig_call, 1), + CALL_EXPR_ARG (orig_call, 2)); + default: + { + tree fntype = TREE_TYPE (fn); + fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fn); + return fold (build_call_array (TREE_TYPE (fntype), + fn, nargs, CALL_EXPR_ARGP (orig_call))); + } + } +} + +static tree +convert_real (tree method_return_type, tree orig_call) +{ + return build1 (VIEW_CONVERT_EXPR, method_return_type, + CALL_EXPR_ARG (orig_call, 0)); +} + + + +/* Provide builtin support for atomic operations. These are + documented at length in libjava/sun/misc/Unsafe.java. */ + +/* FIXME. There are still a few things wrong with this logic. In + particular, atomic writes of multi-word integers are not truly + atomic: this requires more work. + + In general, double-word compare-and-swap cannot portably be + implemented, so we need some kind of fallback for 32-bit machines. + +*/ + + +/* Macros to unmarshal arguments from a CALL_EXPR into a few + variables. We also convert the offset arg from a long to an + integer that is the same size as a pointer. */ + +#define UNMARSHAL3(METHOD_CALL) \ +tree this_arg, obj_arg, offset_arg; \ +do \ +{ \ + tree orig_method_call = METHOD_CALL; \ + this_arg = CALL_EXPR_ARG (orig_method_call, 0); \ + obj_arg = CALL_EXPR_ARG (orig_method_call, 1); \ + offset_arg = fold_convert (java_type_for_size (POINTER_SIZE, 0), \ + CALL_EXPR_ARG (orig_method_call, 2)); \ +} \ +while (0) + +#define UNMARSHAL4(METHOD_CALL) \ +tree value_type, this_arg, obj_arg, offset_arg, value_arg; \ +do \ +{ \ + tree orig_method_call = METHOD_CALL; \ + this_arg = CALL_EXPR_ARG (orig_method_call, 0); \ + obj_arg = CALL_EXPR_ARG (orig_method_call, 1); \ + offset_arg = fold_convert (java_type_for_size (POINTER_SIZE, 0), \ + CALL_EXPR_ARG (orig_method_call, 2)); \ + value_arg = CALL_EXPR_ARG (orig_method_call, 3); \ + value_type = TREE_TYPE (value_arg); \ +} \ +while (0) + +#define UNMARSHAL5(METHOD_CALL) \ +tree value_type, this_arg, obj_arg, offset_arg, expected_arg, value_arg; \ +do \ +{ \ + tree orig_method_call = METHOD_CALL; \ + this_arg = CALL_EXPR_ARG (orig_method_call, 0); \ + obj_arg = CALL_EXPR_ARG (orig_method_call, 1); \ + offset_arg = fold_convert (java_type_for_size (POINTER_SIZE, 0), \ + CALL_EXPR_ARG (orig_method_call, 2)); \ + expected_arg = CALL_EXPR_ARG (orig_method_call, 3); \ + value_arg = CALL_EXPR_ARG (orig_method_call, 4); \ + value_type = TREE_TYPE (value_arg); \ +} \ +while (0) + +/* Add an address to an offset, forming a sum. */ + +static tree +build_addr_sum (tree type, tree addr, tree offset) +{ + tree ptr_type = build_pointer_type (type); + return fold_build2 (POINTER_PLUS_EXPR, + ptr_type, + fold_convert (ptr_type, addr), + fold_convert (sizetype, offset)); +} + +/* Make sure that this-arg is non-NULL. This is a security check. */ + +static tree +build_check_this (tree stmt, tree this_arg) +{ + return build2 (COMPOUND_EXPR, TREE_TYPE (stmt), + java_check_reference (this_arg, 1), stmt); +} + +/* Now the builtins. These correspond to the primitive functions in + libjava/sun/misc/natUnsafe.cc. */ + +static tree +putObject_builtin (tree method_return_type ATTRIBUTE_UNUSED, + tree orig_call) +{ + tree addr, stmt; + UNMARSHAL4 (orig_call); + + addr = build_addr_sum (value_type, obj_arg, offset_arg); + stmt = fold_build2 (MODIFY_EXPR, value_type, + build_java_indirect_ref (value_type, addr, + flag_check_references), + value_arg); + + return build_check_this (stmt, this_arg); +} + +static tree +compareAndSwapInt_builtin (tree method_return_type ATTRIBUTE_UNUSED, + tree orig_call) +{ + enum machine_mode mode = TYPE_MODE (int_type_node); + if (direct_optab_handler (sync_compare_and_swap_optab, mode) + != CODE_FOR_nothing + || flag_use_atomic_builtins) + { + tree addr, stmt; + UNMARSHAL5 (orig_call); + (void) value_type; /* Avoid set but not used warning. */ + + addr = build_addr_sum (int_type_node, obj_arg, offset_arg); + stmt = build_call_expr (built_in_decls[BUILT_IN_BOOL_COMPARE_AND_SWAP_4], + 3, addr, expected_arg, value_arg); + + return build_check_this (stmt, this_arg); + } + return NULL_TREE; +} + +static tree +compareAndSwapLong_builtin (tree method_return_type ATTRIBUTE_UNUSED, + tree orig_call) +{ + enum machine_mode mode = TYPE_MODE (long_type_node); + if (direct_optab_handler (sync_compare_and_swap_optab, mode) + != CODE_FOR_nothing + || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (word_mode) + && flag_use_atomic_builtins)) + /* We don't trust flag_use_atomic_builtins for multi-word + compareAndSwap. Some machines such as ARM have atomic libfuncs + but not the multi-word versions. */ + { + tree addr, stmt; + UNMARSHAL5 (orig_call); + (void) value_type; /* Avoid set but not used warning. */ + + addr = build_addr_sum (long_type_node, obj_arg, offset_arg); + stmt = build_call_expr (built_in_decls[BUILT_IN_BOOL_COMPARE_AND_SWAP_8], + 3, addr, expected_arg, value_arg); + + return build_check_this (stmt, this_arg); + } + return NULL_TREE; +} +static tree +compareAndSwapObject_builtin (tree method_return_type ATTRIBUTE_UNUSED, + tree orig_call) +{ + enum machine_mode mode = TYPE_MODE (ptr_type_node); + if (direct_optab_handler (sync_compare_and_swap_optab, mode) + != CODE_FOR_nothing + || flag_use_atomic_builtins) + { + tree addr, stmt; + int builtin; + + UNMARSHAL5 (orig_call); + builtin = (POINTER_SIZE == 32 + ? BUILT_IN_BOOL_COMPARE_AND_SWAP_4 + : BUILT_IN_BOOL_COMPARE_AND_SWAP_8); + + addr = build_addr_sum (value_type, obj_arg, offset_arg); + stmt = build_call_expr (built_in_decls[builtin], + 3, addr, expected_arg, value_arg); + + return build_check_this (stmt, this_arg); + } + return NULL_TREE; +} + +static tree +putVolatile_builtin (tree method_return_type ATTRIBUTE_UNUSED, + tree orig_call) +{ + tree addr, stmt, modify_stmt; + UNMARSHAL4 (orig_call); + + addr = build_addr_sum (value_type, obj_arg, offset_arg); + addr + = fold_convert (build_pointer_type (build_type_variant (value_type, 0, 1)), + addr); + + stmt = build_call_expr (built_in_decls[BUILT_IN_SYNCHRONIZE], 0); + modify_stmt = fold_build2 (MODIFY_EXPR, value_type, + build_java_indirect_ref (value_type, addr, + flag_check_references), + value_arg); + stmt = build2 (COMPOUND_EXPR, TREE_TYPE (modify_stmt), + stmt, modify_stmt); + + return build_check_this (stmt, this_arg); +} + +static tree +getVolatile_builtin (tree method_return_type ATTRIBUTE_UNUSED, + tree orig_call) +{ + tree addr, stmt, modify_stmt, tmp; + UNMARSHAL3 (orig_call); + (void) this_arg; /* Avoid set but not used warning. */ + + addr = build_addr_sum (method_return_type, obj_arg, offset_arg); + addr + = fold_convert (build_pointer_type (build_type_variant + (method_return_type, 0, 1)), addr); + + stmt = build_call_expr (built_in_decls[BUILT_IN_SYNCHRONIZE], 0); + + tmp = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL, method_return_type); + DECL_IGNORED_P (tmp) = 1; + DECL_ARTIFICIAL (tmp) = 1; + pushdecl (tmp); + + modify_stmt = fold_build2 (MODIFY_EXPR, method_return_type, + tmp, + build_java_indirect_ref (method_return_type, addr, + flag_check_references)); + + stmt = build2 (COMPOUND_EXPR, void_type_node, modify_stmt, stmt); + stmt = build2 (COMPOUND_EXPR, method_return_type, stmt, tmp); + + return stmt; +} + +static tree +VMSupportsCS8_builtin (tree method_return_type, + tree orig_call ATTRIBUTE_UNUSED) +{ + enum machine_mode mode = TYPE_MODE (long_type_node); + gcc_assert (method_return_type == boolean_type_node); + if (direct_optab_handler (sync_compare_and_swap_optab, mode) + != CODE_FOR_nothing) + return boolean_true_node; + else + return boolean_false_node; +} + + + +#define BUILTIN_NOTHROW 1 +#define BUILTIN_CONST 2 +/* Define a single builtin. */ +static void +define_builtin (enum built_in_function val, + const char *name, + tree type, + const char *libname, + int flags) +{ + tree decl; + + decl = build_decl (BUILTINS_LOCATION, + FUNCTION_DECL, get_identifier (name), type); + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + SET_DECL_ASSEMBLER_NAME (decl, get_identifier (libname)); + pushdecl (decl); + DECL_BUILT_IN_CLASS (decl) = BUILT_IN_NORMAL; + DECL_FUNCTION_CODE (decl) = val; + if (flags & BUILTIN_NOTHROW) + TREE_NOTHROW (decl) = 1; + if (flags & BUILTIN_CONST) + TREE_READONLY (decl) = 1; + + implicit_built_in_decls[val] = decl; + built_in_decls[val] = decl; +} + + + +/* Initialize the builtins. */ +void +initialize_builtins (void) +{ + tree double_ftype_double, double_ftype_double_double; + tree float_ftype_float_float; + tree boolean_ftype_boolean_boolean; + int i; + + for (i = 0; java_builtins[i].builtin_code != END_BUILTINS; ++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; + } + + void_list_node = end_params_node; + + float_ftype_float_float + = build_function_type_list (float_type_node, + float_type_node, float_type_node, NULL_TREE); + + double_ftype_double + = build_function_type_list (double_type_node, double_type_node, NULL_TREE); + double_ftype_double_double + = build_function_type_list (double_type_node, + double_type_node, double_type_node, NULL_TREE); + + define_builtin (BUILT_IN_FMOD, "__builtin_fmod", + double_ftype_double_double, "fmod", BUILTIN_CONST); + define_builtin (BUILT_IN_FMODF, "__builtin_fmodf", + float_ftype_float_float, "fmodf", BUILTIN_CONST); + + define_builtin (BUILT_IN_ACOS, "__builtin_acos", + double_ftype_double, "_ZN4java4lang4Math4acosEJdd", + BUILTIN_CONST); + define_builtin (BUILT_IN_ASIN, "__builtin_asin", + double_ftype_double, "_ZN4java4lang4Math4asinEJdd", + BUILTIN_CONST); + define_builtin (BUILT_IN_ATAN, "__builtin_atan", + double_ftype_double, "_ZN4java4lang4Math4atanEJdd", + BUILTIN_CONST); + define_builtin (BUILT_IN_ATAN2, "__builtin_atan2", + double_ftype_double_double, "_ZN4java4lang4Math5atan2EJddd", + BUILTIN_CONST); + define_builtin (BUILT_IN_CEIL, "__builtin_ceil", + double_ftype_double, "_ZN4java4lang4Math4ceilEJdd", + BUILTIN_CONST); + define_builtin (BUILT_IN_COS, "__builtin_cos", + double_ftype_double, "_ZN4java4lang4Math3cosEJdd", + BUILTIN_CONST); + define_builtin (BUILT_IN_EXP, "__builtin_exp", + double_ftype_double, "_ZN4java4lang4Math3expEJdd", + BUILTIN_CONST); + define_builtin (BUILT_IN_FLOOR, "__builtin_floor", + double_ftype_double, "_ZN4java4lang4Math5floorEJdd", + BUILTIN_CONST); + define_builtin (BUILT_IN_LOG, "__builtin_log", + double_ftype_double, "_ZN4java4lang4Math3logEJdd", + BUILTIN_CONST); + define_builtin (BUILT_IN_POW, "__builtin_pow", + double_ftype_double_double, "_ZN4java4lang4Math3powEJddd", + BUILTIN_CONST); + define_builtin (BUILT_IN_SIN, "__builtin_sin", + double_ftype_double, "_ZN4java4lang4Math3sinEJdd", + BUILTIN_CONST); + define_builtin (BUILT_IN_SQRT, "__builtin_sqrt", + double_ftype_double, "_ZN4java4lang4Math4sqrtEJdd", + BUILTIN_CONST); + define_builtin (BUILT_IN_TAN, "__builtin_tan", + double_ftype_double, "_ZN4java4lang4Math3tanEJdd", + BUILTIN_CONST); + + boolean_ftype_boolean_boolean + = build_function_type_list (boolean_type_node, + boolean_type_node, boolean_type_node, + NULL_TREE); + define_builtin (BUILT_IN_EXPECT, "__builtin_expect", + boolean_ftype_boolean_boolean, + "__builtin_expect", + BUILTIN_CONST | BUILTIN_NOTHROW); + define_builtin (BUILT_IN_BOOL_COMPARE_AND_SWAP_4, + "__sync_bool_compare_and_swap_4", + build_function_type_list (boolean_type_node, + int_type_node, + build_pointer_type (int_type_node), + int_type_node, NULL_TREE), + "__sync_bool_compare_and_swap_4", 0); + define_builtin (BUILT_IN_BOOL_COMPARE_AND_SWAP_8, + "__sync_bool_compare_and_swap_8", + build_function_type_list (boolean_type_node, + long_type_node, + build_pointer_type (long_type_node), + int_type_node, NULL_TREE), + "__sync_bool_compare_and_swap_8", 0); + define_builtin (BUILT_IN_SYNCHRONIZE, "__sync_synchronize", + build_function_type_list (void_type_node, NULL_TREE), + "__sync_synchronize", BUILTIN_NOTHROW); + + define_builtin (BUILT_IN_RETURN_ADDRESS, "__builtin_return_address", + build_function_type_list (ptr_type_node, int_type_node, NULL_TREE), + "__builtin_return_address", BUILTIN_NOTHROW); + + build_common_builtin_nodes (); +} + +/* If the call matches a builtin, return the + appropriate builtin expression instead. */ +tree +check_for_builtin (tree method, tree call) +{ + if (optimize && TREE_CODE (call) == CALL_EXPR) + { + int i; + 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)); + + for (i = 0; java_builtins[i].builtin_code != END_BUILTINS; ++i) + { + if (method_class == java_builtins[i].class_name.t + && method_name == java_builtins[i].method_name.t) + { + tree fn; + + if (java_builtins[i].creator != NULL) + { + tree result + = (*java_builtins[i].creator) (method_return_type, call); + return result == NULL_TREE ? call : result; + } + + /* Builtin functions emit a direct call which is incompatible + with the BC-ABI. */ + if (flag_indirect_dispatch) + return call; + fn = built_in_decls[java_builtins[i].builtin_code]; + if (fn == NULL_TREE) + return call; + return java_build_function_call_expr (fn, call); + } + } + } + return call; +} + +#include "gt-java-builtins.h" |