OSDN Git Service

gcc/java
[pf3gnuchains/gcc-fork.git] / gcc / java / decl.c
index ad1b55e..06da90b 100644 (file)
@@ -17,8 +17,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
 
 Java and all Java-based marks are trademarks or registered trademarks
 of Sun Microsystems, Inc. in the United States and other countries.
@@ -61,8 +61,31 @@ static tree create_primitive_vtable (const char *);
 static tree check_local_unnamed_variable (tree, tree, tree);
 static void parse_version (void);
 
-/* Used when computing the ABI version.  */
-#define GCJ_BINARYCOMPAT_ADDITION 5
+
+/* The following ABI flags are used in the high-order bits of the version
+   ID field. The version ID number itself should never be larger than 
+   0xfffff, so it should be safe to use top 12 bits for these flags. */
+
+#define FLAG_BINARYCOMPAT_ABI (1<<31)  /* Class is built with the BC-ABI. */
+
+#define FLAG_BOOTSTRAP_LOADER (1<<30)  /* Used when defining a class that 
+                                         should be loaded by the bootstrap
+                                         loader.  */
+
+/* If an ABI change is made within a GCC release series, rendering current
+   binaries incompatible with the old runtimes, this number can be set to
+   enforce the compatibility rules. */
+#define MINOR_BINARYCOMPAT_ABI_VERSION 0
+
+/* The runtime may recognize a variety of BC ABIs (objects generated by 
+   different version of gcj), but will probably always require strict 
+   matching for the ordinary (C++) ABI.  */
+
+/* The version ID of the BC ABI that we generate.  This must be kept in
+   sync with parse_version(), libgcj, and reality (if the BC format changes, 
+   this must change).  */
+#define GCJ_CURRENT_BC_ABI_VERSION \
+  (4 * 100000 + 0 * 1000 + MINOR_BINARYCOMPAT_ABI_VERSION)
 
 /* The ABI version number.  */
 tree gcj_abi_version;
@@ -97,6 +120,9 @@ static int uniq;
 
 static GTY(()) tree pending_local_decls;
 
+/* The decl for "_Jv_ResolvePoolEntry".  */
+tree soft_resolvepoolentry_node;
+
 #if defined(DEBUG_JAVA_BINDING_LEVELS)
 int binding_depth = 0;
 int is_class_level = 0;
@@ -137,8 +163,7 @@ update_aliases (tree decl, int index, int pc)
   tree decl_type = TREE_TYPE (decl);
   tree tmp;
 
-  if (debug_variable_p (decl))
-    abort ();
+  gcc_assert (! debug_variable_p (decl));
 
   for (tmp = TREE_VEC_ELT (decl_map, index); 
        tmp != NULL_TREE; 
@@ -149,7 +174,10 @@ update_aliases (tree decl, int index, int pc)
          && LOCAL_SLOT_P (tmp) == 0
          && (pc == -1
              || (pc >= DECL_LOCAL_START_PC (tmp)
-                 && pc <= DECL_LOCAL_END_PC (tmp)))
+                 && pc < DECL_LOCAL_END_PC (tmp)))
+         /* This test is < (rather than <=) because there's no point
+            updating an alias that's about to die at the end of this
+            instruction.  */
          && (tmp_type == decl_type
              || (INTEGRAL_TYPE_P (tmp_type)
                  && INTEGRAL_TYPE_P (decl_type)
@@ -159,8 +187,7 @@ update_aliases (tree decl, int index, int pc)
                  && TREE_CODE (decl_type) == POINTER_TYPE)))
        {
          tree src = build1 (NOP_EXPR, tmp_type, decl);
-         if (LOCAL_VAR_OUT_OF_SCOPE_P (tmp))
-           abort ();
+         gcc_assert (! LOCAL_VAR_OUT_OF_SCOPE_P (tmp));
          java_add_stmt (build2 (MODIFY_EXPR, tmp_type, tmp, src));
        }
     }
@@ -240,8 +267,7 @@ check_local_unnamed_variable (tree best, tree decl, tree type)
 {
   tree decl_type = TREE_TYPE (decl);
   
-  if (LOCAL_VAR_OUT_OF_SCOPE_P (decl))
-    abort ();
+  gcc_assert (! LOCAL_VAR_OUT_OF_SCOPE_P (decl));
 
   /* Use the same decl for all integer types <= 32 bits.  This is
      necessary because sometimes a value is stored as (for example)
@@ -263,24 +289,14 @@ check_local_unnamed_variable (tree best, tree decl, tree type)
         initially held a pointer arg -- or vice versa -- we create a
         new VAR_DECL.  
 
-        ???: As long as verification is correct, this will be a
+        ???: As long as verification is correct, this will be a
         compatible type.  But maybe we should create a dummy variable
         and replace all references to it with the DECL and a
-        NOP_EXPR.
+        NOP_EXPR.  
       */
       || (TREE_CODE (decl_type) == POINTER_TYPE
          && TREE_CODE (decl) == PARM_DECL
-         && TREE_CODE (type) == POINTER_TYPE)
-
-      /* The new verifier requires a similar treatment in the
-        situation where the parameter has an integral type which
-        promotes to `int'.  */
-      || (flag_new_verifier
-         && TREE_CODE (decl) == PARM_DECL
-         && INTEGRAL_TYPE_P (decl_type)
-         && TYPE_PRECISION (decl_type) <= 32
-         && INTEGRAL_TYPE_P (type)
-         && TYPE_PRECISION (type) <= 32))
+         && TREE_CODE (type) == POINTER_TYPE))
     {
       if (best == NULL_TREE
          || (decl_type == type && TREE_TYPE (best) != type))
@@ -312,6 +328,16 @@ find_local_variable (int index, tree type, int pc ATTRIBUTE_UNUSED)
       tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
     }
 
+  /* gcj has a function called promote_type(), which is used by both
+     the bytecode compiler and the source compiler.  Unfortunately,
+     the type systems for the Java VM and the Java language are not
+     the same: a boolean in the VM promotes to an int, not to a wide
+     boolean.  If our caller wants something to hold a boolean, that
+     had better be an int, because that slot might be re-used
+     later in integer context.  */
+  if (TREE_CODE (type) == BOOLEAN_TYPE)
+    type = integer_type_node;
+
   /* If we don't find a match, create one with the type passed in.
      The name of the variable is #n#m, which n is the variable index
      in the local variable area and m is a dummy identifier for
@@ -382,9 +408,7 @@ java_replace_reference (tree var_decl, bool want_lvalue)
          int index = DECL_LOCAL_SLOT_NUMBER (var_decl);
          tree base_decl = TREE_VEC_ELT (base_decl_map, index); 
 
-         if (! base_decl)
-           abort ();
-
+         gcc_assert (base_decl);
          if (! want_lvalue)
            base_decl = build1 (NOP_EXPR, decl_type, base_decl);
 
@@ -514,6 +538,7 @@ push_promoted_type (const char *name, tree actual_type)
   TYPE_MAX_VALUE (type) = copy_node (in_max);
   TREE_TYPE (TYPE_MAX_VALUE (type)) = type;
   TYPE_PRECISION (type) = TYPE_PRECISION (int_type_node);
+  TYPE_STRING_FLAG (type) = TYPE_STRING_FLAG (actual_type);
   layout_type (type);
   pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
   return type;
@@ -541,7 +566,6 @@ builtin_function (const char *name,
   TREE_PUBLIC (decl) = 1;
   if (library_name)
     SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
-  make_decl_rtl (decl);
   pushdecl (decl);
   DECL_BUILT_IN_CLASS (decl) = cl;
   DECL_FUNCTION_CODE (decl) = function_code;
@@ -597,16 +621,20 @@ parse_version (void)
       ++p;
     }
 
-  /* Implicit in this computation is the idea that we won't break the
-     old-style binary ABI in a sub-minor release (e.g., from 4.0.0 to
-     4.0.1).  */
-  abi_version = 10000 * major + 10 * minor;
-  /* It is helpful to distinguish BC ABI from ordinary ABI at this
-     level, since at some point we will recognize a variety of BC ABIs
-     (objects generated by different version of gcj), but will
-     probably always require strict matching for ordinary ABI.  */
   if (flag_indirect_dispatch)
-    abi_version += GCJ_BINARYCOMPAT_ADDITION;
+    {
+      abi_version = GCJ_CURRENT_BC_ABI_VERSION;
+      abi_version |= FLAG_BINARYCOMPAT_ABI;
+    }
+  else /* C++ ABI */
+    {
+      /* Implicit in this computation is the idea that we won't break the
+        old-style binary ABI in a sub-minor release (e.g., from 4.0.0 to
+        4.0.1).  */
+      abi_version = 100000 * major + 1000 * minor;
+    }
+  if (flag_bootstrap_classes)
+    abi_version |= FLAG_BOOTSTRAP_LOADER;
 
   gcj_abi_version = build_int_cstu (ptr_type_node, abi_version);
 }
@@ -711,7 +739,8 @@ java_init_decl_processing (void)
      initializations of __FUNCTION__ and __PRETTY_FUNCTION__.  */
   short_array_type_node = build_prim_array_type (short_type_node, 200);
 #endif
-  char_type_node = make_node (CHAR_TYPE);
+  char_type_node = make_node (INTEGER_TYPE);
+  TYPE_STRING_FLAG (char_type_node) = 1;
   TYPE_PRECISION (char_type_node) = 16;
   fixup_unsigned_type (char_type_node);
   pushdecl (build_decl (TYPE_DECL, get_identifier ("char"), char_type_node));
@@ -989,8 +1018,7 @@ java_init_decl_processing (void)
 
   endlink = end_params_node = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
 
-  t = tree_cons (NULL_TREE, class_ptr_type,
-                tree_cons (NULL_TREE, int_type_node, endlink));
+  t = tree_cons (NULL_TREE, class_ptr_type, endlink);
   alloc_object_node = builtin_function ("_Jv_AllocObject",
                                        build_function_type (ptr_type_node, t),
                                        0, NOT_BUILT_IN, NULL, NULL_TREE);
@@ -1006,33 +1034,41 @@ java_init_decl_processing (void)
                                          build_function_type (void_type_node,
                                                               t),
                                          0, NOT_BUILT_IN, NULL, NULL_TREE);
-
+  t = tree_cons (NULL_TREE, class_ptr_type,
+                tree_cons (NULL_TREE, int_type_node, endlink));
+  soft_resolvepoolentry_node 
+    = builtin_function ("_Jv_ResolvePoolEntry", 
+                       build_function_type (ptr_type_node, t),
+                       0,NOT_BUILT_IN, NULL, NULL_TREE);
+  DECL_IS_PURE (soft_resolvepoolentry_node) = 1;
   throw_node = builtin_function ("_Jv_Throw",
-                                build_function_type (ptr_type_node, t),
+                                build_function_type (void_type_node, t),
                                 0, NOT_BUILT_IN, NULL, NULL_TREE);
   /* Mark throw_nodes as `noreturn' functions with side effects.  */
   TREE_THIS_VOLATILE (throw_node) = 1;
   TREE_SIDE_EFFECTS (throw_node) = 1;
 
-  t = build_function_type (int_type_node, endlink);
+  t = build_function_type (void_type_node, tree_cons (NULL_TREE, ptr_type_node,
+                                                     endlink));
   soft_monitorenter_node 
     = builtin_function ("_Jv_MonitorEnter", t, 0, NOT_BUILT_IN,
                        NULL, NULL_TREE);
   soft_monitorexit_node 
     = builtin_function ("_Jv_MonitorExit", t, 0, NOT_BUILT_IN,
                        NULL, NULL_TREE);
-  
-  t = tree_cons (NULL_TREE, int_type_node, 
+
+  t = tree_cons (NULL_TREE, ptr_type_node, 
                 tree_cons (NULL_TREE, int_type_node, endlink));
   soft_newarray_node
       = builtin_function ("_Jv_NewPrimArray",
-                         build_function_type(ptr_type_node, t),
+                         build_function_type (ptr_type_node, t),
                          0, NOT_BUILT_IN, NULL, NULL_TREE);
   DECL_IS_MALLOC (soft_newarray_node) = 1;
 
   t = tree_cons (NULL_TREE, int_type_node,
                 tree_cons (NULL_TREE, class_ptr_type,
-                           tree_cons (NULL_TREE, object_ptr_type_node, endlink)));
+                           tree_cons (NULL_TREE, object_ptr_type_node,
+                                      endlink)));
   soft_anewarray_node
       = builtin_function ("_Jv_NewObjectArray",
                          build_function_type (ptr_type_node, t),
@@ -1068,6 +1104,24 @@ java_init_decl_processing (void)
   TREE_THIS_VOLATILE (soft_nullpointer_node) = 1;
   TREE_SIDE_EFFECTS (soft_nullpointer_node) = 1;
 
+  soft_abstractmethod_node
+    = builtin_function ("_Jv_ThrowAbstractMethodError",
+                       build_function_type (void_type_node, endlink),
+                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+  /* Mark soft_abstractmethod_node as a `noreturn' function with side
+     effects.  */
+  TREE_THIS_VOLATILE (soft_abstractmethod_node) = 1;
+  TREE_SIDE_EFFECTS (soft_abstractmethod_node) = 1;
+
+  soft_nosuchfield_node
+    = builtin_function ("_Jv_ThrowNoSuchFieldError",
+                       build_function_type (void_type_node, endlink),
+                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+  /* Mark soft_nosuchfield_node as a `noreturn' function with side
+     effects.  */
+  TREE_THIS_VOLATILE (soft_nosuchfield_node) = 1;
+  TREE_SIDE_EFFECTS (soft_nosuchfield_node) = 1;
+
   t = tree_cons (NULL_TREE, class_ptr_type,
                 tree_cons (NULL_TREE, object_ptr_type_node, endlink));
   soft_checkcast_node
@@ -1118,9 +1172,17 @@ java_init_decl_processing (void)
                        0, NOT_BUILT_IN, NULL, NULL_TREE);
   soft_jnipopsystemframe_node
     = builtin_function ("_Jv_JNI_PopSystemFrame",
-                       build_function_type (ptr_type_node, t),
+                       build_function_type (void_type_node, t),
+                       0, NOT_BUILT_IN, NULL, NULL_TREE);
+
+  t = tree_cons (NULL_TREE, object_ptr_type_node, endlink);
+  soft_unwrapjni_node
+    = builtin_function ("_Jv_UnwrapJNIweakReference",
+                       build_function_type (object_ptr_type_node, t),
                        0, NOT_BUILT_IN, NULL, NULL_TREE);
 
+  t = tree_cons (NULL_TREE, int_type_node,
+                tree_cons (NULL_TREE, int_type_node, endlink));
   soft_idiv_node
     = builtin_function ("_Jv_divI",
                        build_function_type (int_type_node, t),
@@ -1131,6 +1193,8 @@ java_init_decl_processing (void)
                        build_function_type (int_type_node, t),
                        0, NOT_BUILT_IN, NULL, NULL_TREE);
 
+  t = tree_cons (NULL_TREE, long_type_node,
+                tree_cons (NULL_TREE, long_type_node, endlink));
   soft_ldiv_node
     = builtin_function ("_Jv_divJ",
                        build_function_type (long_type_node, t),
@@ -1145,6 +1209,7 @@ java_init_decl_processing (void)
   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
                                              ? "__gcj_personality_sj0"
                                              : "__gcj_personality_v0");
+  default_init_unwind_resume_libfunc ();
 
   lang_eh_runtime_type = do_nothing;
 
@@ -1178,7 +1243,7 @@ lookup_name (tree name)
 }
 
 /* Similar to `lookup_name' but look only at current binding level and
-   the previous one if its the parameter level.  */
+   the previous one if it's the parameter level.  */
 
 static tree
 lookup_name_current_level (tree name)
@@ -1257,7 +1322,7 @@ pushdecl (tree x)
        /* error_mark_node is 0 for a while during initialization!  */
        {
          t = 0;
-         error ("%J'%D' used prior to declaration", x, x);
+         error ("%q+D used prior to declaration", x);
        }
 
       /* If we're naming a hitherto-unnamed type, set its TYPE_NAME
@@ -1331,7 +1396,7 @@ pushdecl (tree x)
                warnstring = "declaration of %qs shadows global declaration";
 
              if (warnstring)
-               warning (warnstring, IDENTIFIER_POINTER (name));
+               warning (0, warnstring, IDENTIFIER_POINTER (name));
            }
 #endif
 
@@ -1629,12 +1694,12 @@ poplevel (int keep, int reverse, int functionbody)
 
          if (DECL_INITIAL (label) == 0)
            {
-             error ("%Jlabel '%D' used but not defined", label, label);
+             error ("label %q+D used but not defined", label);
              /* Avoid crashing later.  */
              define_label (input_location, DECL_NAME (label));
            }
          else if (warn_unused[UNUSED_LABEL] && !TREE_USED (label))
-           warning ("%Jlabel '%D' defined but not used", label, label);
+           warning (0, "label %q+D defined but not used", label);
          IDENTIFIER_LABEL_VALUE (DECL_NAME (label)) = 0;
 
          /* Put the labels into the "variables" of the
@@ -1741,6 +1806,12 @@ maybe_poplevels (int pc)
   current_pc = pc;
 #endif
 
+  /* FIXME: I'm pretty sure that this is wrong.  Variable scopes are
+     inclusive, so a variable is live if pc == end_pc.  Here, we
+     terminate a range if the current pc is equal to the end of the
+     range, and this is *before* we have generated code for the
+     instruction at end_pc.  We're closing a binding level one
+     instruction too early.*/
   while (current_binding_level->end_pc <= pc)
     poplevel (1, 0, 0);
 }
@@ -1756,8 +1827,8 @@ force_poplevels (int start_pc)
   while (current_binding_level->start_pc > start_pc)
     {
       if (pedantic && current_binding_level->start_pc > start_pc)
-       warning ("%JIn %D: overlapped variable and exception ranges at %d",
-                 current_function_decl, current_function_decl,
+       warning (0, "In %+D: overlapped variable and exception ranges at %d",
+                 current_function_decl,
                 current_binding_level->start_pc);
       poplevel (1, 0, 0);
     }
@@ -1818,9 +1889,8 @@ give_name_to_locals (JCF *jcf)
        {
          tree decl = TREE_VEC_ELT (decl_map, slot);
          DECL_NAME (decl) = name;
-         SET_DECL_ASSEMBLER_NAME (decl, name);
          if (TREE_CODE (decl) != PARM_DECL || TREE_TYPE (decl) != type)
-           warning ("bad type in parameter debug info");
+           warning (0, "bad type in parameter debug info");
        }
       else
        {
@@ -1829,8 +1899,8 @@ give_name_to_locals (JCF *jcf)
          tree decl = build_decl (VAR_DECL, name, type);
          if (end_pc > DECL_CODE_LENGTH (current_function_decl))
            {
-             warning ("%Jbad PC range for debug info for local '%D'",
-                       decl, decl);
+             warning (0, "bad PC range for debug info for local %q+D",
+                       decl);
              end_pc = DECL_CODE_LENGTH (current_function_decl);
            }
 
@@ -1885,7 +1955,6 @@ give_name_to_locals (JCF *jcf)
              sprintf (buffer, "ARG_%d", arg_i);
              DECL_NAME (parm) = get_identifier (buffer);
            }
-         SET_DECL_ASSEMBLER_NAME (parm, DECL_NAME (parm));
        }
     }
 }
@@ -1938,8 +2007,7 @@ start_java_method (tree fndecl)
     {
       tree parm_name = NULL_TREE, parm_decl;
       tree parm_type = TREE_VALUE (tem);
-      if (i >= DECL_MAX_LOCALS (fndecl))
-       abort ();
+      gcc_assert (i < DECL_MAX_LOCALS (fndecl));
 
       parm_decl = build_decl (PARM_DECL, parm_name, parm_type);
       DECL_CONTEXT (parm_decl) = fndecl;
@@ -2000,7 +2068,6 @@ end_java_method (void)
                     attach_init_test_initialization_flags, block_body);
     }
 
-  flag_unit_at_a_time = 0;
   finish_method (fndecl);
 
   if (! flag_unit_at_a_time)
@@ -2038,7 +2105,9 @@ finish_method (tree fndecl)
 
   /* Prepend class initialization for static methods reachable from
      other classes.  */
-  if (METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl)
+  if (METHOD_STATIC (fndecl)
+      && (! METHOD_PRIVATE (fndecl)
+          || INNER_CLASS_P (DECL_CONTEXT (fndecl)))
       && ! DECL_CLINIT_P (fndecl)
       && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (fndecl))))
     {
@@ -2089,10 +2158,39 @@ java_mark_decl_local (tree decl)
 
   /* If we've already constructed DECL_RTL, give encode_section_info
      a second chance, now that we've changed the flags.  */
+  /* ??? Ideally, we'd have flag_unit_at_a_time set, and not have done
+     anything that would have referenced DECL_RTL so far.  But at the
+     moment we force flag_unit_at_a_time off due to excessive memory
+     consumption when compiling large jar files.  Which probably means
+     that we need to re-order how we process jar files...  */
   if (DECL_RTL_SET_P (decl))
     make_decl_rtl (decl);
 }
 
+/* Given appropriate target support, G++ will emit hidden aliases for native
+   methods.  Using this hidden name is required for proper operation of
+   _Jv_Method::ncode, but it doesn't hurt to use it everywhere.  Look for
+   proper target support, then mark the method for aliasing.  */
+
+static void
+java_mark_cni_decl_local (tree decl)
+{
+  /* Setting DECL_LOCAL_CNI_METHOD_P changes the behavior of the mangler.
+     We expect that we should not yet have referenced this decl in a 
+     context that requires it.  Check this invariant even if we don't have
+     support for hidden aliases.  */
+  gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
+
+#if !defined(HAVE_GAS_HIDDEN) || !defined(ASM_OUTPUT_DEF)
+  return;
+#endif
+
+  DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+  DECL_LOCAL_CNI_METHOD_P (decl) = 1;
+}
+
+/* Use the preceding two functions and mark all members of the class.  */
+
 void
 java_mark_class_local (tree class)
 {
@@ -2103,8 +2201,13 @@ java_mark_class_local (tree class)
       java_mark_decl_local (t);
 
   for (t = TYPE_METHODS (class); t ; t = TREE_CHAIN (t))
-    if (!METHOD_ABSTRACT (t) && (!METHOD_NATIVE (t) || flag_jni))
-      java_mark_decl_local (t);
+    if (!METHOD_ABSTRACT (t))
+      {
+       if (METHOD_NATIVE (t) && !flag_jni)
+         java_mark_cni_decl_local (t);
+        else
+         java_mark_decl_local (t);
+      }
 }
 
 /* Add a statement to a compound_expr.  */
@@ -2170,8 +2273,7 @@ get_stmts (void)
 void
 register_exception_range (struct eh_range *range, int pc, int end_pc)
 {
-  if (current_binding_level->exception_range)
-    abort ();
+  gcc_assert (! current_binding_level->exception_range);
   current_binding_level->exception_range = range;
   current_binding_level->end_pc = end_pc;
   current_binding_level->start_pc = pc;