/* Java(TM) language-specific utility routines.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GCC.
static bool java_init (void);
static void java_finish (void);
-static int java_init_options (void);
+static unsigned int java_init_options (unsigned int, const char **);
static bool java_post_options (const char **);
static int java_handle_option (size_t scode, const char *arg, int value);
static bool java_dump_tree (void *, tree);
static void dump_compound_expr (dump_info_p, tree);
static bool java_decl_ok_for_sibcall (tree);
+static tree java_get_callee_fndecl (tree);
#ifndef TARGET_OBJECT_SUFFIX
# define TARGET_OBJECT_SUFFIX ".o"
/* When zero, don't optimize static class initialization. This flag shouldn't
be tested alone, use STATIC_CLASS_INITIALIZATION_OPTIMIZATION_P instead. */
-int flag_optimize_sci = 1;
+/* FIXME: Make this work with gimplify. */
+int flag_optimize_sci = 0;
/* When nonzero, use offset tables for virtual method calls
in order to improve binary compatibility. */
int flag_store_check = 1;
/* When nonzero, print extra version information. */
-static int version_flag = 0;
+static int v_flag = 0;
/* Set nonzero if the user specified -finline-functions on the command
line. */
#undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE java_signed_or_unsigned_type
-#undef LANG_HOOKS_TREE_INLINING_WALK_SUBTREES
-#define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES java_tree_inlining_walk_subtrees
-
#undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN java_dump_tree
+#undef LANG_HOOKS_GIMPLIFY_EXPR
+#define LANG_HOOKS_GIMPLIFY_EXPR java_gimplify_expr
+
+#undef LANG_HOOKS_TREE_INLINING_WALK_SUBTREES
+#define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES java_tree_inlining_walk_subtrees
+
#undef LANG_HOOKS_DECL_OK_FOR_SIBCALL
#define LANG_HOOKS_DECL_OK_FOR_SIBCALL java_decl_ok_for_sibcall
+#undef LANG_HOOKS_GET_CALLEE_FNDECL
+#define LANG_HOOKS_GET_CALLEE_FNDECL java_get_callee_fndecl
+
+#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
+#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION java_expand_body
+
/* Each front end provides its own. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
static int
java_handle_option (size_t scode, const char *arg, int value)
{
- const struct cl_option *option = &cl_options[scode];
enum opt_code code = (enum opt_code) scode;
- /* Ignore file names. */
- if (code == N_OPTS)
- return 1;
-
- if (arg == NULL && (option->flags & (CL_JOINED | CL_SEPARATE)))
- {
- /* These can take an empty argument. */
- if (code == OPT_fassume_compiled_
- || code == OPT_fclasspath_
- || code == OPT_fCLASSPATH_
- || code == OPT_fbootclasspath_)
- arg = "";
- else
- {
- error ("missing argument to \"-%s\"", option->opt_text);
- return 1;
- }
- }
-
switch (code)
{
default:
dependency_tracking |= DEPEND_ENABLE;
break;
- case OPT_MD:
+ case OPT_MD_:
jcf_dependency_init (1);
dependency_tracking |= DEPEND_SET_FILE | DEPEND_ENABLE;
break;
dependency_tracking |= DEPEND_ENABLE;
break;
- case OPT_MMD:
+ case OPT_MMD_:
jcf_dependency_init (0);
dependency_tracking |= DEPEND_SET_FILE | DEPEND_ENABLE;
break;
flag_assert = value;
break;
+ case OPT_fenable_assertions_:
+ add_enable_assert (arg, value);
+ break;
+
+ case OPT_fenable_assertions:
+ add_enable_assert ("", value);
+ break;
+
+ case OPT_fdisable_assertions_:
+ add_enable_assert (arg, !value);
+ break;
+
+ case OPT_fdisable_assertions:
+ add_enable_assert ("", !value);
+ break;
+
case OPT_fassume_compiled_:
add_assume_compiled (arg, !value);
break;
break;
case OPT_fdump_:
- if (!dump_switch_p (option->opt_text + strlen ("f")))
+ if (!dump_switch_p (arg))
return 0;
break;
break;
case OPT_version:
- version_flag = 1;
+ v_flag = 1;
break;
}
if (flag_inline_functions)
flag_inline_trees = 1;
+ /* FIXME: Indirect dispatch isn't yet compatible with static class
+ init optimization. */
+ if (flag_indirect_dispatch)
+ always_initialize_class_p = true;
+
/* Force minimum function alignment if g++ uses the least significant
bit of function pointers to store the virtual bit. This is required
to keep vtables compatible. */
&& force_align_functions_log < 1)
force_align_functions_log = 1;
- jcf_path_seal (version_flag);
+ jcf_path_seal (v_flag);
java_init_decl_processing ();
inhibit_error_function_printing = (level == 1);
}
-static int
-java_init_options (void)
+static unsigned int
+java_init_options (unsigned int argc ATTRIBUTE_UNUSED,
+ const char **argv ATTRIBUTE_UNUSED)
{
flag_bounds_check = 1;
flag_exceptions = 1;
/* In Java arithmetic overflow always wraps around. */
flag_wrapv = 1;
+ /* Java requires left-to-right evaluation of subexpressions. */
+ flag_evaluation_order = 1;
+
jcf_path_init ();
- return CL_JAVA;
+ return CL_Java;
}
static bool
{
const char *filename = *pfilename;
- /* Use tree inlining if possible. Function instrumentation is only
- done in the RTL level, so we disable tree inlining. */
- if (! flag_instrument_function_entry_exit)
+ /* Use tree inlining. */
+ if (!flag_no_inline)
+ flag_no_inline = 1;
+ if (flag_inline_functions)
{
- if (!flag_no_inline)
- flag_no_inline = 1;
- if (flag_inline_functions)
- {
- flag_inline_trees = 2;
- flag_inline_functions = 0;
- }
+ flag_inline_trees = 2;
+ flag_inline_functions = 0;
}
/* Open input file. */
switch (code)
{
case BLOCK:
- if (BLOCK_EXPR_BODY (t))
- {
- tree *prev = &BLOCK_EXPR_BODY (*tp);
- while (*prev)
- {
- WALK_SUBTREE (*prev);
- prev = &TREE_CHAIN (*prev);
- }
- }
+ WALK_SUBTREE (BLOCK_EXPR_BODY (t));
return NULL_TREE;
- break;
default:
return NULL_TREE;
}
+
+ #undef WALK_SUBTREE
}
/* Called from unsafe_for_reeval. */
if (!*init_test_decl)
*init_test_decl = (tree)n->value;
+ /* This fixes a weird case.
+
+ The front end assumes that once we have called a method that
+ initializes some class, we can assume the class is initialized. It
+ does this by setting the DECL_INITIAL of the init_test_decl for that
+ class, and no initializations are emitted for that class.
+
+ However, what if the method that is suppoed to do the initialization
+ is itself inlined in the caller? When expanding the called method
+ we'll assume that the class initialization has already been done,
+ because the DECL_INITIAL of the init_test_decl is set.
+
+ To fix this we remove the DECL_INITIAL (in the caller scope) of all
+ the init_test_decls corresponding to classes initialized by the
+ inlined method. This makes the caller no longer assume that the
+ method being inlined does any class initializations. */
+ DECL_INITIAL (*init_test_decl) = NULL;
+
return true;
}
(DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), ite->key);
if (! h)
return true;
-
splay_tree_insert (decl_map,
(splay_tree_key) ite->value,
(splay_tree_value) h);
-
return true;
}
static bool
java_decl_ok_for_sibcall (tree decl)
{
- return decl != NULL && DECL_CONTEXT (decl) == current_class;
+ return decl != NULL && DECL_CONTEXT (decl) == output_class;
+}
+
+/* Given a call_expr, try to figure out what its target might be. In
+ the case of an indirection via the atable, search for the decl. If
+ the decl is external, we return NULL. If we don't, the optimizer
+ will replace the indirection with a direct call, which undoes the
+ purpose of the atable indirection. */
+static tree
+java_get_callee_fndecl (tree call_expr)
+{
+ tree method, table, element, atable_methods;
+
+ HOST_WIDE_INT index;
+
+ if (TREE_CODE (call_expr) != CALL_EXPR)
+ return NULL;
+ method = TREE_OPERAND (call_expr, 0);
+ STRIP_NOPS (method);
+ if (TREE_CODE (method) != ARRAY_REF)
+ return NULL;
+ table = TREE_OPERAND (method, 0);
+ if (! DECL_LANG_SPECIFIC(table)
+ || !DECL_OWNER (table)
+ || TYPE_ATABLE_DECL (DECL_OWNER (table)) != table)
+ return NULL;
+
+ atable_methods = TYPE_ATABLE_METHODS (DECL_OWNER (table));
+ index = TREE_INT_CST_LOW (TREE_OPERAND (method, 1));
+
+ /* FIXME: Replace this for loop with a hash table lookup. */
+ for (element = atable_methods; element; element = TREE_CHAIN (element))
+ {
+ if (index == 1)
+ {
+ tree purpose = TREE_PURPOSE (element);
+ if (TREE_CODE (purpose) == FUNCTION_DECL
+ && ! DECL_EXTERNAL (purpose))
+ return purpose;
+ else
+ return NULL;
+ }
+ --index;
+ }
+
+ return NULL;
}
#include "gt-java-lang.h"