OSDN Git Service

PR 44103
[pf3gnuchains/gcc-fork.git] / gcc / java / constants.c
index 98a0504..ca5eb77 100644 (file)
@@ -1,12 +1,12 @@
 /* Handle the constant pool of the Java(TM) Virtual Machine.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
-   Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
+   2007, 2008  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 2, or (at your option)
+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,
@@ -14,9 +14,8 @@ 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 GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. 
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>. 
 
 Java and all Java-based marks are trademarks or registered trademarks
 of Sun Microsystems, Inc. in the United States and other countries.
@@ -34,11 +33,8 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 
 static void set_constant_entry (CPool *, int, int, jword);
 static int find_tree_constant (CPool *, int, tree);
-static int find_class_or_string_constant (CPool *, int, tree);
 static int find_name_and_type_constant (CPool *, tree, tree);
 static tree get_tag_node (int);
-static tree build_constant_data_ref (void);
-static CPool *cpool_for_class (tree);
 
 /* Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. */
 
@@ -48,9 +44,8 @@ set_constant_entry (CPool *cpool, int index, int tag, jword value)
   if (cpool->data == NULL)
     {
       cpool->capacity = 100;
-      cpool->tags = ggc_alloc_cleared (sizeof(uint8) * cpool->capacity);
-      cpool->data = ggc_alloc_cleared (sizeof(union cpool_entry)
-                                      * cpool->capacity);
+      cpool->tags = GGC_CNEWVEC (uint8, cpool->capacity);
+      cpool->data = GGC_CNEWVEC (union cpool_entry, cpool->capacity);
       cpool->count = 1;
     }
   if (index >= cpool->capacity)
@@ -59,10 +54,9 @@ set_constant_entry (CPool *cpool, int index, int tag, jword value)
       cpool->capacity *= 2;
       if (index >= cpool->capacity)
        cpool->capacity = index + 10;
-      cpool->tags = ggc_realloc (cpool->tags, 
-                                sizeof(uint8) * cpool->capacity);
-      cpool->data = ggc_realloc (cpool->data,
-                                sizeof(union cpool_entry) * cpool->capacity);
+      cpool->tags = GGC_RESIZEVEC (uint8, cpool->tags, cpool->capacity);
+      cpool->data = GGC_RESIZEVEC (union cpool_entry, cpool->data,
+                                  cpool->capacity);
 
       /* Make sure GC never sees uninitialized tag values.  */
       memset (cpool->tags + old_cap, 0, cpool->capacity - old_cap);
@@ -134,7 +128,7 @@ find_utf8_constant (CPool *cpool, tree name)
   return find_tree_constant (cpool, CONSTANT_Utf8, name);
 }
 
-static int
+int
 find_class_or_string_constant (CPool *cpool, int tag, tree name)
 {
   jword j = find_utf8_constant (cpool, name);
@@ -322,6 +316,9 @@ get_tag_node (int tag)
 {
   /* A Cache for build_int_cst (CONSTANT_XXX, 0). */
 
+  if (tag >= 13)
+    return build_int_cst (NULL_TREE, tag);
+
   if (tag_nodes[tag] == NULL_TREE)
     tag_nodes[tag] = build_int_cst (NULL_TREE, tag);
   return tag_nodes[tag];
@@ -329,15 +326,15 @@ get_tag_node (int tag)
 
 /* Given a class, return its constant pool, creating one if necessary.  */
 
-static CPool *
-cpool_for_class (tree class)
+CPool *
+cpool_for_class (tree klass)
 {
-  CPool *cpool = TYPE_CPOOL (class);
+  CPool *cpool = TYPE_CPOOL (klass);
 
   if (cpool == NULL)
     {
-      cpool = ggc_alloc_cleared (sizeof (struct CPool));
-      TYPE_CPOOL (class) = cpool;
+      cpool = GGC_CNEW (struct CPool);
+      TYPE_CPOOL (klass) = cpool;
     }
   return cpool;
 }
@@ -373,13 +370,13 @@ find_name_and_type_constant_tree (CPool *cpool, tree name, tree type)
 }
 
 /* Look for a field ref that matches DECL in the constant pool of
-   CLASS.  
+   KLASS.  
    Return the index of the entry.  */
 
 int
-alloc_constant_fieldref (tree class, tree decl)
+alloc_constant_fieldref (tree klass, tree decl)
 {
-  CPool *outgoing_cpool = cpool_for_class (class);
+  CPool *outgoing_cpool = cpool_for_class (klass);
   int class_index 
     = find_tree_constant (outgoing_cpool, CONSTANT_Class, 
                          DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
@@ -423,32 +420,56 @@ alloc_class_constant (tree clas)
 
 /* Return the decl of the data array of the current constant pool. */
 
-static tree
-build_constant_data_ref (void)
+tree
+build_constant_data_ref (bool indirect)
 {
-  tree decl = TYPE_CPOOL_DATA_REF (output_class);
-
-  if (decl == NULL_TREE)
+  if (indirect)
+    {
+      tree d;
+      tree cpool_type = build_array_type (ptr_type_node, NULL_TREE);
+      tree decl = build_class_ref (output_class);
+      tree klass = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (decl)),
+                          decl);
+      tree constants = build3 (COMPONENT_REF, 
+                              TREE_TYPE (constants_field_decl_node), klass,
+                              constants_field_decl_node,
+                              NULL_TREE);
+      tree data = build3 (COMPONENT_REF, 
+                         TREE_TYPE (constants_data_field_decl_node), 
+                         constants,
+                         constants_data_field_decl_node,
+                         NULL_TREE);
+
+      TREE_THIS_NOTRAP (klass) = 1;
+      data = fold_convert (build_pointer_type (cpool_type), data);
+      d = build1 (INDIRECT_REF, cpool_type, data);
+
+      return d;
+    }
+  else
     {
-      tree type;
       tree decl_name = mangled_classname ("_CD_", output_class);
+      tree decl = IDENTIFIER_GLOBAL_VALUE (decl_name);
 
-      /* Build a type with unspecified bounds.  The will make sure
-        that targets do the right thing with whatever size we end
-        up with at the end.  Using bounds that are too small risks
-        assuming the data is in the small data section.  */
-      type = build_array_type (ptr_type_node, NULL_TREE);
-
-      /* We need to lay out the type ourselves, since build_array_type
-        thinks the type is incomplete.  */
-      layout_type (type);
+      if (! decl)
+       {
+         /* Build a type with unspecified bounds.  The will make sure
+            that targets do the right thing with whatever size we end
+            up with at the end.  Using bounds that are too small risks
+            assuming the data is in the small data section.  */
+         tree type = build_array_type (ptr_type_node, NULL_TREE);
+
+         /* We need to lay out the type ourselves, since build_array_type
+            thinks the type is incomplete.  */
+         layout_type (type);
+
+         decl = build_decl (input_location, VAR_DECL, decl_name, type);
+         TREE_STATIC (decl) = 1;
+         IDENTIFIER_GLOBAL_VALUE (decl_name) = decl;
+       }
 
-      decl = build_decl (VAR_DECL, decl_name, type);
-      TREE_STATIC (decl) = 1;
-      TYPE_CPOOL_DATA_REF (output_class) = decl;
+      return decl;
     }
-
-  return decl;
 }
 
 /* Get the pointer value at the INDEX'th element of the constant pool. */
@@ -456,10 +477,16 @@ build_constant_data_ref (void)
 tree
 build_ref_from_constant_pool (int index)
 {
-  tree d = build_constant_data_ref ();
-  tree i = build_int_cst (NULL_TREE, index);
-  return build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i,
+  tree i;
+  tree d = TYPE_CPOOL_DATA_REF (output_class);
+
+  if (d == NULL_TREE)
+    d = build_constant_data_ref (flag_indirect_classes);
+
+  i = build_int_cst (NULL_TREE, index);
+  d = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i,
                 NULL_TREE, NULL_TREE);
+  return d;
 }
 
 /* Build an initializer for the constants field of the current constant pool.
@@ -473,18 +500,35 @@ build_constants_constructor (void)
   tree cons;
   tree tags_list = NULL_TREE;
   tree data_list = NULL_TREE;
+  VEC(constructor_elt,gc) *v = NULL;
   int i;
+
   for (i = outgoing_cpool->count;  --i > 0; )
-    switch (outgoing_cpool->tags[i])
+    switch (outgoing_cpool->tags[i] & ~CONSTANT_LazyFlag)
       {
+      case CONSTANT_None:  /* The second half of a Double or Long on a
+                             32-bit target.  */
       case CONSTANT_Fieldref:
       case CONSTANT_NameAndType:
+      case CONSTANT_Float:
+      case CONSTANT_Integer:
+      case CONSTANT_Double:
+      case CONSTANT_Long:
+      case CONSTANT_Methodref:
+      case CONSTANT_InterfaceMethodref:
        {
-         jword temp = outgoing_cpool->data[i].w;
+         unsigned HOST_WIDE_INT temp = outgoing_cpool->data[i].w;
+
+         /* Make sure that on a big-endian machine with 64-bit
+            pointers this 32-bit jint appears in the first word.
+            FIXME: This is a kludge.  The field we're initializing is
+            not a scalar but a union, and that's how we should
+            represent it in the compiler.  We should fix this.  */
+         if (BYTES_BIG_ENDIAN && POINTER_SIZE > 32)
+           temp <<= POINTER_SIZE - 32;
 
          tags_list
-           = tree_cons (NULL_TREE, 
-                        build_int_cst (NULL_TREE, outgoing_cpool->tags[i]),
+           = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
                         tags_list);
          data_list
            = tree_cons (NULL_TREE, 
@@ -493,7 +537,11 @@ build_constants_constructor (void)
                         data_list);
        }
        break;
-      default:
+
+      case CONSTANT_Class:
+      case CONSTANT_String:
+      case CONSTANT_Unicode:
+      case CONSTANT_Utf8:
        tags_list
          = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
                       tags_list);
@@ -501,19 +549,31 @@ build_constants_constructor (void)
          = tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t),
                       data_list);
        break;
+
+      default:
+       gcc_assert (false);
       }
   if (outgoing_cpool->count > 0)
     {
       tree data_decl, tags_decl, tags_type;
       tree max_index = build_int_cst (sizetype, outgoing_cpool->count - 1);
       tree index_type = build_index_type (max_index);
+      tree tem;
 
       /* Add dummy 0'th element of constant pool. */
       tags_list = tree_cons (NULL_TREE, get_tag_node (0), tags_list);
       data_list = tree_cons (NULL_TREE, null_pointer_node, data_list);
   
-      data_decl = build_constant_data_ref ();
+      /* Change the type of the decl to have the proper array size.
+         ???  Make sure to transition the old type-pointer-to list to this
+        new type to not invalidate all build address expressions.  */
+      data_decl = build_constant_data_ref (false);
+      tem = TYPE_POINTER_TO (TREE_TYPE (data_decl));
+      if (!tem)
+       tem = build_pointer_type (TREE_TYPE (data_decl));
+      TYPE_POINTER_TO (TREE_TYPE (data_decl)) = NULL_TREE;
       TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type);
+      TYPE_POINTER_TO (TREE_TYPE (data_decl)) = tem;
       DECL_INITIAL (data_decl) = build_constructor_from_list
                                  (TREE_TYPE (data_decl), data_list);
       DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
@@ -522,7 +582,8 @@ build_constants_constructor (void)
       data_value = build_address_of (data_decl);
 
       tags_type = build_array_type (unsigned_byte_type_node, index_type);
-      tags_decl = build_decl (VAR_DECL, mangled_classname ("_CT_", 
+      tags_decl = build_decl (input_location, 
+                             VAR_DECL, mangled_classname ("_CT_", 
                                                           current_class),
                              tags_type);
       TREE_STATIC (tags_decl) = 1;
@@ -536,12 +597,12 @@ build_constants_constructor (void)
       data_value = null_pointer_node;
       tags_value = null_pointer_node;
     }
-  START_RECORD_CONSTRUCTOR (cons, constants_type_node);
-  PUSH_FIELD_VALUE (cons, "size",
+  START_RECORD_CONSTRUCTOR (v, constants_type_node);
+  PUSH_FIELD_VALUE (v, "size",
                    build_int_cst (NULL_TREE, outgoing_cpool->count));
-  PUSH_FIELD_VALUE (cons, "tags", tags_value);
-  PUSH_FIELD_VALUE (cons, "data", data_value);
-  FINISH_RECORD_CONSTRUCTOR (cons);
+  PUSH_FIELD_VALUE (v, "tags", tags_value);
+  PUSH_FIELD_VALUE (v, "data", data_value);
+  FINISH_RECORD_CONSTRUCTOR (cons, v, constants_type_node);
   return cons;
 }