OSDN Git Service

PR c++/51662
[pf3gnuchains/gcc-fork.git] / gcc / java / constants.c
index 526d9c7..4425338 100644 (file)
@@ -1,6 +1,6 @@
 /* Handle the constant pool of the Java(TM) Virtual Machine.
    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
-   2007, 2008  Free Software Foundation, Inc.
+   2007, 2008, 2010  Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -28,6 +28,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "jcf.h"
 #include "tree.h"
 #include "java-tree.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "ggc.h"
 
@@ -44,8 +45,11 @@ set_constant_entry (CPool *cpool, int index, int tag, jword value)
   if (cpool->data == NULL)
     {
       cpool->capacity = 100;
-      cpool->tags = GGC_CNEWVEC (uint8, cpool->capacity);
-      cpool->data = GGC_CNEWVEC (union cpool_entry, cpool->capacity);
+      cpool->tags = (uint8 *) ggc_alloc_cleared_atomic (sizeof (uint8)
+                                               * cpool->capacity);
+      cpool->data = ggc_alloc_cleared_vec_cpool_entry (sizeof
+                                                      (union cpool_entry),
+                                                      cpool->capacity);
       cpool->count = 1;
     }
   if (index >= cpool->capacity)
@@ -333,7 +337,7 @@ cpool_for_class (tree klass)
 
   if (cpool == NULL)
     {
-      cpool = GGC_CNEW (struct CPool);
+      cpool = ggc_alloc_cleared_CPool ();
       TYPE_CPOOL (klass) = cpool;
     }
   return cpool;
@@ -463,7 +467,7 @@ build_constant_data_ref (bool indirect)
             thinks the type is incomplete.  */
          layout_type (type);
 
-         decl = build_decl (VAR_DECL, decl_name, type);
+         decl = build_decl (input_location, VAR_DECL, decl_name, type);
          TREE_STATIC (decl) = 1;
          IDENTIFIER_GLOBAL_VALUE (decl_name) = decl;
        }
@@ -498,10 +502,23 @@ build_constants_constructor (void)
   CPool *outgoing_cpool = cpool_for_class (current_class);
   tree tags_value, data_value;
   tree cons;
-  tree tags_list = NULL_TREE;
-  tree data_list = NULL_TREE;
+  VEC(constructor_elt,gc) *v = NULL;
   int i;
+  VEC(constructor_elt,gc) *tags = NULL;
+  VEC(constructor_elt,gc) *data = NULL;
+  constructor_elt *t = NULL;
+  constructor_elt *d = NULL;
 
+  if (outgoing_cpool->count > 0)
+    {
+      int c = outgoing_cpool->count;
+      VEC_safe_grow_cleared (constructor_elt, gc, tags, c);
+      VEC_safe_grow_cleared (constructor_elt, gc, data, c);
+      t = VEC_index (constructor_elt, tags, c-1);
+      d = VEC_index (constructor_elt, data, c-1);
+    }
+
+#define CONSTRUCTOR_PREPEND_VALUE(E, V) E->value = V, E--
   for (i = outgoing_cpool->count;  --i > 0; )
     switch (outgoing_cpool->tags[i] & ~CONSTANT_LazyFlag)
       {
@@ -523,17 +540,14 @@ build_constants_constructor (void)
             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, get_tag_node (outgoing_cpool->tags[i]),
-                        tags_list);
-         data_list
-           = tree_cons (NULL_TREE, 
-                        fold_convert (ptr_type_node, 
-                                      (build_int_cst (NULL_TREE, temp))),
-                        data_list);
+         if (BYTES_BIG_ENDIAN)
+           temp <<= ((POINTER_SIZE > 32) ? POINTER_SIZE - 32 : 0);
+
+          CONSTRUCTOR_PREPEND_VALUE (t, get_tag_node (outgoing_cpool->tags[i]));
+          CONSTRUCTOR_PREPEND_VALUE (d,
+                                     fold_convert (ptr_type_node, 
+                                                   (build_int_cst (NULL_TREE,
+                                                                   temp))));
        }
        break;
 
@@ -541,43 +555,51 @@ build_constants_constructor (void)
       case CONSTANT_String:
       case CONSTANT_Unicode:
       case CONSTANT_Utf8:
-       tags_list
-         = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
-                      tags_list);
-       data_list
-         = tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t),
-                      data_list);
+        CONSTRUCTOR_PREPEND_VALUE (t, get_tag_node (outgoing_cpool->tags[i]));
+        CONSTRUCTOR_PREPEND_VALUE (d, build_utf8_ref (outgoing_cpool->data[i].t));
        break;
 
       default:
        gcc_assert (false);
       }
+#undef CONSTRUCTOR_PREPEND_VALUE
+
   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);
+      gcc_assert (t == VEC_address (constructor_elt, tags));
+      gcc_assert (d == VEC_address (constructor_elt, data));
+      t->value = get_tag_node (0);
+      d->value = null_pointer_node;
   
+      /* 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);
-      DECL_INITIAL (data_decl) = build_constructor_from_list
-                                 (TREE_TYPE (data_decl), data_list);
+      TYPE_POINTER_TO (TREE_TYPE (data_decl)) = tem;
+      DECL_INITIAL (data_decl) = build_constructor (TREE_TYPE (data_decl), data);
       DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
       DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl));
       rest_of_decl_compilation (data_decl, 1, 0);
       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;
-      DECL_INITIAL (tags_decl) = build_constructor_from_list
-                                (tags_type, tags_list);
+      DECL_INITIAL (tags_decl) = build_constructor (tags_type, tags);
       rest_of_decl_compilation (tags_decl, 1, 0);
       tags_value = build_address_of (tags_decl);
     }
@@ -586,12 +608,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;
 }