OSDN Git Service

2010-06-02 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / java / constants.c
1 /* Handle the constant pool of the Java(TM) Virtual Machine.
2    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
3    2007, 2008  Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>. 
19
20 Java and all Java-based marks are trademarks or registered trademarks
21 of Sun Microsystems, Inc. in the United States and other countries.
22 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
23
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "jcf.h"
29 #include "tree.h"
30 #include "java-tree.h"
31 #include "toplev.h"
32 #include "ggc.h"
33
34 static void set_constant_entry (CPool *, int, int, jword);
35 static int find_tree_constant (CPool *, int, tree);
36 static int find_name_and_type_constant (CPool *, tree, tree);
37 static tree get_tag_node (int);
38
39 /* Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. */
40
41 static void
42 set_constant_entry (CPool *cpool, int index, int tag, jword value)
43 {
44   if (cpool->data == NULL)
45     {
46       cpool->capacity = 100;
47       cpool->tags = GGC_CNEWVEC (uint8, cpool->capacity);
48       cpool->data = GGC_CNEWVEC (union cpool_entry, cpool->capacity);
49       cpool->count = 1;
50     }
51   if (index >= cpool->capacity)
52     {
53       int old_cap = cpool->capacity;
54       cpool->capacity *= 2;
55       if (index >= cpool->capacity)
56         cpool->capacity = index + 10;
57       cpool->tags = GGC_RESIZEVEC (uint8, cpool->tags, cpool->capacity);
58       cpool->data = GGC_RESIZEVEC (union cpool_entry, cpool->data,
59                                    cpool->capacity);
60
61       /* Make sure GC never sees uninitialized tag values.  */
62       memset (cpool->tags + old_cap, 0, cpool->capacity - old_cap);
63       memset (cpool->data + old_cap, 0,
64               (cpool->capacity - old_cap) * sizeof (union cpool_entry));
65     }
66   if (index >= cpool->count)
67     cpool->count = index + 1;
68   cpool->tags[index] = tag;
69   cpool->data[index].w = value;
70 }
71
72 /* Find (or create) a constant pool entry matching TAG and VALUE. */
73
74 int
75 find_constant1 (CPool *cpool, int tag, jword value)
76 {
77   int i;
78   for (i = cpool->count;  --i > 0; )
79     {
80       if (cpool->tags[i] == tag && cpool->data[i].w == value)
81         return i;
82     }
83   i = cpool->count == 0 ? 1 : cpool->count;
84   set_constant_entry (cpool, i, tag, value);
85   return i;
86 }
87
88 /* Find a double-word constant pool entry matching TAG and WORD1/WORD2. */
89
90 int
91 find_constant2 (CPool *cpool, int tag, jword word1, jword word2)
92 {
93   int i;
94   for (i = cpool->count - 1;  --i > 0; )
95     {
96       if (cpool->tags[i] == tag
97           && cpool->data[i].w == word1
98           && cpool->data[i+1].w == word2)
99         return i;
100     }
101   i = cpool->count == 0 ? 1 : cpool->count;
102   set_constant_entry (cpool, i, tag, word1);
103   set_constant_entry (cpool, i+1, 0, word2);
104   return i;
105 }
106
107 static int
108 find_tree_constant (CPool *cpool, int tag, tree value)
109 {
110   int i;
111   for (i = cpool->count;  --i > 0; )
112     {
113       if (cpool->tags[i] == tag && cpool->data[i].t == value)
114         return i;
115     }
116   i = cpool->count == 0 ? 1 : cpool->count;
117   set_constant_entry (cpool, i, tag, 0);
118   cpool->data[i].t = value;
119   return i;
120 }
121
122
123 int
124 find_utf8_constant (CPool *cpool, tree name)
125 {
126   if (name == NULL_TREE)
127     return 0;
128   return find_tree_constant (cpool, CONSTANT_Utf8, name);
129 }
130
131 int
132 find_class_or_string_constant (CPool *cpool, int tag, tree name)
133 {
134   jword j = find_utf8_constant (cpool, name);
135   int i;
136   for (i = cpool->count;  --i > 0; )
137     {
138       if (cpool->tags[i] == tag && cpool->data[i].w == j)
139         return i;
140     }
141   i = cpool->count;
142   set_constant_entry (cpool, i, tag, j);
143   return i;
144 }
145
146 int
147 find_class_constant (CPool *cpool, tree type)
148 {
149   return find_class_or_string_constant (cpool, CONSTANT_Class,
150                                         build_internal_class_name (type));
151 }
152
153 /* Allocate a CONSTANT_string entry given a STRING_CST. */
154
155 int
156 find_string_constant (CPool *cpool, tree string)
157 {
158   string = get_identifier (TREE_STRING_POINTER (string));
159   return find_class_or_string_constant (cpool, CONSTANT_String, string);
160
161 }
162
163 /* Find (or create) a CONSTANT_NameAndType matching NAME and TYPE.
164    Return its index in the constant pool CPOOL. */
165
166 static int
167 find_name_and_type_constant (CPool *cpool, tree name, tree type)
168 {
169   int name_index = find_utf8_constant (cpool, name);
170   int type_index = find_utf8_constant (cpool, build_java_signature (type));
171   return find_constant1 (cpool, CONSTANT_NameAndType,
172                          (name_index << 16) | type_index);
173 }
174
175 /* Find (or create) a CONSTANT_Fieldref for DECL (a FIELD_DECL or VAR_DECL).
176    Return its index in the constant pool CPOOL. */
177
178 int
179 find_fieldref_index (CPool *cpool, tree decl)
180 {
181   int class_index = find_class_constant (cpool, DECL_CONTEXT (decl));
182   int name_type_index
183     = find_name_and_type_constant (cpool, DECL_NAME (decl), TREE_TYPE (decl));
184   return find_constant1 (cpool, CONSTANT_Fieldref,
185                          (class_index << 16) | name_type_index);
186 }
187
188 /* Find (or create) a CONSTANT_Methodref for DECL (a FUNCTION_DECL).
189    Return its index in the constant pool CPOOL. */
190
191 int
192 find_methodref_index (CPool *cpool, tree decl)
193 {
194   return find_methodref_with_class_index (cpool, decl, DECL_CONTEXT (decl));
195 }
196
197 int
198 find_methodref_with_class_index (CPool *cpool, tree decl, tree mclass)
199 {
200   int class_index = find_class_constant (cpool, mclass);
201   tree name = DECL_CONSTRUCTOR_P (decl) ? init_identifier_node
202     : DECL_NAME (decl);
203   int name_type_index;
204   name_type_index = 
205       find_name_and_type_constant (cpool, name, TREE_TYPE (decl));
206   return find_constant1 (cpool,
207                          CLASS_INTERFACE (TYPE_NAME (mclass))
208                          ? CONSTANT_InterfaceMethodref
209                          : CONSTANT_Methodref,
210                          (class_index << 16) | name_type_index);
211 }
212
213 #define PUT1(X)  (*ptr++ = (X))
214 #define PUT2(X)  (PUT1((X) >> 8), PUT1(X))
215 #define PUT4(X)  (PUT2((X) >> 16), PUT2(X))
216 #define PUTN(P, N)  (memcpy(ptr, (P), (N)), ptr += (N))
217
218 /* Give the number of bytes needed in a .class file for the CPOOL
219    constant pool.  Includes the 2-byte constant_pool_count. */
220
221 int
222 count_constant_pool_bytes (CPool *cpool)
223 {
224   int size = 2;
225   int i = 1;
226   for ( ;  i < cpool->count;  i++)
227     {
228       size++;
229       switch (cpool->tags[i])
230         {
231         case CONSTANT_NameAndType:
232         case CONSTANT_Fieldref:
233         case CONSTANT_Methodref:
234         case CONSTANT_InterfaceMethodref:
235         case CONSTANT_Float:
236         case CONSTANT_Integer:
237           size += 4;
238           break;
239         case CONSTANT_Class:
240         case CONSTANT_String:
241           size += 2;
242           break;
243         case CONSTANT_Long:
244         case CONSTANT_Double:
245           size += 8;
246           i++;
247           break;
248         case CONSTANT_Utf8:
249           {
250             tree t = cpool->data[i].t;
251             int len = IDENTIFIER_LENGTH (t);
252             size += len + 2;
253           }
254           break;
255         default:
256           /* Second word of CONSTANT_Long and  CONSTANT_Double. */
257           size--;
258         }
259     }
260   return size;
261 }
262
263 /* Write the constant pool CPOOL into BUFFER.
264    The length of BUFFER is LENGTH, which must match the needed length. */
265
266 void
267 write_constant_pool (CPool *cpool, unsigned char *buffer, int length)
268 {
269   unsigned char *ptr = buffer;
270   int i = 1;
271   union cpool_entry *datap = &cpool->data[1];
272   PUT2 (cpool->count);
273   for ( ;  i < cpool->count;  i++, datap++)
274     {
275       int tag = cpool->tags[i];
276       PUT1 (tag);
277       switch (tag)
278         {
279         case CONSTANT_NameAndType:
280         case CONSTANT_Fieldref:
281         case CONSTANT_Methodref:
282         case CONSTANT_InterfaceMethodref:
283         case CONSTANT_Float:
284         case CONSTANT_Integer:
285           PUT4 (datap->w);
286           break;
287         case CONSTANT_Class:
288         case CONSTANT_String:
289           PUT2 (datap->w);
290           break;
291           break;
292         case CONSTANT_Long:
293         case CONSTANT_Double:
294           PUT4(datap->w);
295           i++;
296           datap++;
297           PUT4 (datap->w);
298           break;
299         case CONSTANT_Utf8:
300           {
301             tree t = datap->t;
302             int len = IDENTIFIER_LENGTH (t);
303             PUT2 (len);
304             PUTN (IDENTIFIER_POINTER (t), len);
305           }
306           break;
307         }
308     }
309
310   gcc_assert (ptr == buffer + length);
311 }
312
313 static GTY(()) tree tag_nodes[13];
314 static tree
315 get_tag_node (int tag)
316 {
317   /* A Cache for build_int_cst (CONSTANT_XXX, 0). */
318
319   if (tag >= 13)
320     return build_int_cst (NULL_TREE, tag);
321
322   if (tag_nodes[tag] == NULL_TREE)
323     tag_nodes[tag] = build_int_cst (NULL_TREE, tag);
324   return tag_nodes[tag];
325 }
326
327 /* Given a class, return its constant pool, creating one if necessary.  */
328
329 CPool *
330 cpool_for_class (tree klass)
331 {
332   CPool *cpool = TYPE_CPOOL (klass);
333
334   if (cpool == NULL)
335     {
336       cpool = GGC_CNEW (struct CPool);
337       TYPE_CPOOL (klass) = cpool;
338     }
339   return cpool;
340 }
341
342 /* Look for a constant pool entry that matches TAG and NAME.
343    Creates a new entry if not found.
344    TAG is one of CONSTANT_Utf8, CONSTANT_String or CONSTANT_Class.
345    NAME is an IDENTIFIER_NODE naming the Utf8 constant, string, or class.
346    Returns the index of the entry. */
347
348 int
349 alloc_name_constant (int tag, tree name)
350 {
351   CPool *outgoing_cpool = cpool_for_class (output_class);
352   return find_tree_constant (outgoing_cpool, tag, name);
353 }
354
355 /* Create a constant pool entry for a name_and_type.  This one has '.'
356    rather than '/' because it isn't going into a class file, it's
357    going into a compiled object.  We don't use the '/' separator in
358    compiled objects.  */
359
360 static int
361 find_name_and_type_constant_tree (CPool *cpool, tree name, tree type)
362 {
363   int name_index = find_utf8_constant (cpool, name);
364   int type_index 
365     = find_utf8_constant (cpool, 
366                           identifier_subst (build_java_signature (type), 
367                                             "", '/', '.', ""));
368   return find_constant1 (cpool, CONSTANT_NameAndType,
369                          (name_index << 16) | type_index);
370 }
371
372 /* Look for a field ref that matches DECL in the constant pool of
373    KLASS.  
374    Return the index of the entry.  */
375
376 int
377 alloc_constant_fieldref (tree klass, tree decl)
378 {
379   CPool *outgoing_cpool = cpool_for_class (klass);
380   int class_index 
381     = find_tree_constant (outgoing_cpool, CONSTANT_Class, 
382                           DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
383   int name_type_index
384     = find_name_and_type_constant_tree (outgoing_cpool, DECL_NAME (decl), 
385                                         TREE_TYPE (decl));
386   return find_constant1 (outgoing_cpool, CONSTANT_Fieldref,
387                          (class_index << 16) | name_type_index);
388 }
389
390 /* Build an identifier for the internal name of reference type TYPE. */
391
392 tree
393 build_internal_class_name (tree type)
394 {
395   tree name;
396   if (TYPE_ARRAY_P (type))
397     name = build_java_signature (type);
398   else
399     {
400       name = TYPE_NAME (type);
401       if (TREE_CODE (name) != IDENTIFIER_NODE)
402         name = DECL_NAME (name);
403       name = identifier_subst (name, "", '.', '/', "");
404     }
405   return name;
406 }
407
408 /* Look for a CONSTANT_Class entry for CLAS, creating a new one if needed. */
409
410 int
411 alloc_class_constant (tree clas)
412 {
413   tree class_name = build_internal_class_name (clas);
414   
415   return alloc_name_constant (CONSTANT_Class,
416                               (unmangle_classname 
417                                (IDENTIFIER_POINTER(class_name),
418                                 IDENTIFIER_LENGTH(class_name))));
419 }
420
421 /* Return the decl of the data array of the current constant pool. */
422
423 tree
424 build_constant_data_ref (bool indirect)
425 {
426   if (indirect)
427     {
428       tree d;
429       tree cpool_type = build_array_type (ptr_type_node, NULL_TREE);
430       tree decl = build_class_ref (output_class);
431       tree klass = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (decl)),
432                            decl);
433       tree constants = build3 (COMPONENT_REF, 
434                                TREE_TYPE (constants_field_decl_node), klass,
435                                constants_field_decl_node,
436                                NULL_TREE);
437       tree data = build3 (COMPONENT_REF, 
438                           TREE_TYPE (constants_data_field_decl_node), 
439                           constants,
440                           constants_data_field_decl_node,
441                           NULL_TREE);
442
443       TREE_THIS_NOTRAP (klass) = 1;
444       data = fold_convert (build_pointer_type (cpool_type), data);
445       d = build1 (INDIRECT_REF, cpool_type, data);
446
447       return d;
448     }
449   else
450     {
451       tree decl_name = mangled_classname ("_CD_", output_class);
452       tree decl = IDENTIFIER_GLOBAL_VALUE (decl_name);
453
454       if (! decl)
455         {
456           /* Build a type with unspecified bounds.  The will make sure
457              that targets do the right thing with whatever size we end
458              up with at the end.  Using bounds that are too small risks
459              assuming the data is in the small data section.  */
460           tree type = build_array_type (ptr_type_node, NULL_TREE);
461
462           /* We need to lay out the type ourselves, since build_array_type
463              thinks the type is incomplete.  */
464           layout_type (type);
465
466           decl = build_decl (input_location, VAR_DECL, decl_name, type);
467           TREE_STATIC (decl) = 1;
468           IDENTIFIER_GLOBAL_VALUE (decl_name) = decl;
469         }
470
471       return decl;
472     }
473 }
474
475 /* Get the pointer value at the INDEX'th element of the constant pool. */
476
477 tree
478 build_ref_from_constant_pool (int index)
479 {
480   tree i;
481   tree d = TYPE_CPOOL_DATA_REF (output_class);
482
483   if (d == NULL_TREE)
484     d = build_constant_data_ref (flag_indirect_classes);
485
486   i = build_int_cst (NULL_TREE, index);
487   d = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i,
488                  NULL_TREE, NULL_TREE);
489   return d;
490 }
491
492 /* Build an initializer for the constants field of the current constant pool.
493    Should only be called at top-level, since it may emit declarations. */
494
495 tree
496 build_constants_constructor (void)
497 {
498   CPool *outgoing_cpool = cpool_for_class (current_class);
499   tree tags_value, data_value;
500   tree cons;
501   tree tags_list = NULL_TREE;
502   tree data_list = NULL_TREE;
503   VEC(constructor_elt,gc) *v = NULL;
504   int i;
505
506   for (i = outgoing_cpool->count;  --i > 0; )
507     switch (outgoing_cpool->tags[i] & ~CONSTANT_LazyFlag)
508       {
509       case CONSTANT_None:  /* The second half of a Double or Long on a
510                               32-bit target.  */
511       case CONSTANT_Fieldref:
512       case CONSTANT_NameAndType:
513       case CONSTANT_Float:
514       case CONSTANT_Integer:
515       case CONSTANT_Double:
516       case CONSTANT_Long:
517       case CONSTANT_Methodref:
518       case CONSTANT_InterfaceMethodref:
519         {
520           unsigned HOST_WIDE_INT temp = outgoing_cpool->data[i].w;
521
522           /* Make sure that on a big-endian machine with 64-bit
523              pointers this 32-bit jint appears in the first word.
524              FIXME: This is a kludge.  The field we're initializing is
525              not a scalar but a union, and that's how we should
526              represent it in the compiler.  We should fix this.  */
527           if (BYTES_BIG_ENDIAN && POINTER_SIZE > 32)
528             temp <<= POINTER_SIZE - 32;
529
530           tags_list
531             = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
532                          tags_list);
533           data_list
534             = tree_cons (NULL_TREE, 
535                          fold_convert (ptr_type_node, 
536                                        (build_int_cst (NULL_TREE, temp))),
537                          data_list);
538         }
539         break;
540
541       case CONSTANT_Class:
542       case CONSTANT_String:
543       case CONSTANT_Unicode:
544       case CONSTANT_Utf8:
545         tags_list
546           = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
547                        tags_list);
548         data_list
549           = tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t),
550                        data_list);
551         break;
552
553       default:
554         gcc_assert (false);
555       }
556   if (outgoing_cpool->count > 0)
557     {
558       tree data_decl, tags_decl, tags_type;
559       tree max_index = build_int_cst (sizetype, outgoing_cpool->count - 1);
560       tree index_type = build_index_type (max_index);
561       tree tem;
562
563       /* Add dummy 0'th element of constant pool. */
564       tags_list = tree_cons (NULL_TREE, get_tag_node (0), tags_list);
565       data_list = tree_cons (NULL_TREE, null_pointer_node, data_list);
566   
567       /* Change the type of the decl to have the proper array size.
568          ???  Make sure to transition the old type-pointer-to list to this
569          new type to not invalidate all build address expressions.  */
570       data_decl = build_constant_data_ref (false);
571       tem = TYPE_POINTER_TO (TREE_TYPE (data_decl));
572       if (!tem)
573         tem = build_pointer_type (TREE_TYPE (data_decl));
574       TYPE_POINTER_TO (TREE_TYPE (data_decl)) = NULL_TREE;
575       TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type);
576       TYPE_POINTER_TO (TREE_TYPE (data_decl)) = tem;
577       DECL_INITIAL (data_decl) = build_constructor_from_list
578                                   (TREE_TYPE (data_decl), data_list);
579       DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
580       DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl));
581       rest_of_decl_compilation (data_decl, 1, 0);
582       data_value = build_address_of (data_decl);
583
584       tags_type = build_array_type (unsigned_byte_type_node, index_type);
585       tags_decl = build_decl (input_location, 
586                               VAR_DECL, mangled_classname ("_CT_", 
587                                                            current_class),
588                               tags_type);
589       TREE_STATIC (tags_decl) = 1;
590       DECL_INITIAL (tags_decl) = build_constructor_from_list
591                                  (tags_type, tags_list);
592       rest_of_decl_compilation (tags_decl, 1, 0);
593       tags_value = build_address_of (tags_decl);
594     }
595   else
596     {
597       data_value = null_pointer_node;
598       tags_value = null_pointer_node;
599     }
600   START_RECORD_CONSTRUCTOR (v, constants_type_node);
601   PUSH_FIELD_VALUE (v, "size",
602                     build_int_cst (NULL_TREE, outgoing_cpool->count));
603   PUSH_FIELD_VALUE (v, "tags", tags_value);
604   PUSH_FIELD_VALUE (v, "data", data_value);
605   FINISH_RECORD_CONSTRUCTOR (cons, v, constants_type_node);
606   return cons;
607 }
608
609 #include "gt-java-constants.h"