OSDN Git Service

* langhooks.h (builtin_function): New langhook.
[pf3gnuchains/gcc-fork.git] / gcc / java / lang.c
index 8fd4ba0..d3ba372 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
@@ -50,7 +50,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 
 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);
@@ -66,6 +66,8 @@ static bool java_can_use_bit_fields_p (void);
 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);
+static void java_clear_binding_stack (void);
 
 #ifndef TARGET_OBJECT_SUFFIX
 # define TARGET_OBJECT_SUFFIX ".o"
@@ -171,7 +173,8 @@ int flag_force_classes_archive_check;
 
 /* 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. */
@@ -181,7 +184,7 @@ int flag_indirect_dispatch = 0;
 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.  */
@@ -222,8 +225,6 @@ struct language_function GTY(())
 #define LANG_HOOKS_UNSAFE_FOR_REEVAL java_unsafe_for_reeval
 #undef LANG_HOOKS_MARK_ADDRESSABLE
 #define LANG_HOOKS_MARK_ADDRESSABLE java_mark_addressable
-#undef LANG_HOOKS_EXPAND_EXPR
-#define LANG_HOOKS_EXPAND_EXPR java_expand_expr
 #undef LANG_HOOKS_TRUTHVALUE_CONVERSION
 #define LANG_HOOKS_TRUTHVALUE_CONVERSION java_truthvalue_conversion
 #undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
@@ -246,15 +247,27 @@ struct language_function GTY(())
 #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
+
+#undef LANG_HOOKS_CLEAR_BINDING_STACK
+#define LANG_HOOKS_CLEAR_BINDING_STACK java_clear_binding_stack
+
 /* Each front end provides its own.  */
 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
@@ -265,28 +278,8 @@ 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:
@@ -301,7 +294,7 @@ java_handle_option (size_t scode, const char *arg, int value)
       dependency_tracking |= DEPEND_ENABLE;
       break;
 
-    case OPT_MD:
+    case OPT_MD_:
       jcf_dependency_init (1);
       dependency_tracking |= DEPEND_SET_FILE | DEPEND_ENABLE;
       break;
@@ -316,7 +309,7 @@ java_handle_option (size_t scode, const char *arg, int value)
       dependency_tracking |= DEPEND_ENABLE;
       break;
 
-    case OPT_MMD:
+    case OPT_MMD_:
       jcf_dependency_init (0);
       dependency_tracking |= DEPEND_SET_FILE | DEPEND_ENABLE;
       break;
@@ -359,6 +352,22 @@ java_handle_option (size_t scode, const char *arg, int value)
       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;
@@ -385,7 +394,7 @@ java_handle_option (size_t scode, const char *arg, int value)
       break;
 
     case OPT_fdump_:
-      if (!dump_switch_p (option->opt_text + strlen ("f")))
+      if (!dump_switch_p (arg))
        return 0;
       break;
 
@@ -448,7 +457,7 @@ java_handle_option (size_t scode, const char *arg, int value)
       break;
 
     case OPT_version:
-      version_flag = 1;
+      v_flag = 1;
       break;
     }
 
@@ -469,6 +478,11 @@ java_init (void)
   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.  */
@@ -476,7 +490,7 @@ java_init (void)
       && force_align_functions_log < 1)
     force_align_functions_log = 1;
 
-  jcf_path_seal (version_flag);
+  jcf_path_seal (v_flag);
 
   java_init_decl_processing ();
 
@@ -675,13 +689,15 @@ java_print_error_function (diagnostic_context *context ATTRIBUTE_UNUSED,
    2, function prototypes are fully resolved and can be printed when
    reporting errors.  */
 
-void lang_init_source (int level)
+void
+lang_init_source (int level)
 {
   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;
@@ -693,9 +709,12 @@ java_init_options (void)
   /* 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
@@ -712,17 +731,13 @@ java_post_options (const char **pfilename)
 {
   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.  */
@@ -841,21 +856,14 @@ java_tree_inlining_walk_subtrees (tree *tp ATTRIBUTE_UNUSED,
   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.  */
@@ -927,6 +935,24 @@ merge_init_test_initialization (void **entry, void *x)
   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;
 }
 
@@ -957,11 +983,9 @@ inline_init_test_initialization (void **entry, void *x)
     (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;
 }
 
@@ -1092,7 +1116,61 @@ java_dump_tree (void *dump_info, tree t)
 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;
+}
+
+
+/* Clear the binding stack.  */
+static void
+java_clear_binding_stack (void)
+{
+  while (!global_bindings_p ())
+    poplevel (0, 0, 0);
 }
 
 #include "gt-java-lang.h"