OSDN Git Service

[gcc/ChangeLog]
[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 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GCC; see the file COPYING.  If not, write to
17 the Free Software Foundation, 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. 
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_class_or_string_constant (CPool *, int, tree);
37 static int find_name_and_type_constant (CPool *, tree, tree);
38 static tree get_tag_node (int);
39 static tree build_constant_data_ref (void);
40 static CPool *cpool_for_class (tree);
41
42 /* Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. */
43
44 static void
45 set_constant_entry (CPool *cpool, int index, int tag, jword value)
46 {
47   if (cpool->data == NULL)
48     {
49       cpool->capacity = 100;
50       cpool->tags = ggc_alloc_cleared (sizeof(uint8) * cpool->capacity);
51       cpool->data = ggc_alloc_cleared (sizeof(union cpool_entry)
52                                        * cpool->capacity);
53       cpool->count = 1;
54     }
55   if (index >= cpool->capacity)
56     {
57       int old_cap = cpool->capacity;
58       cpool->capacity *= 2;
59       if (index >= cpool->capacity)
60         cpool->capacity = index + 10;
61       cpool->tags = ggc_realloc (cpool->tags, 
62                                  sizeof(uint8) * cpool->capacity);
63       cpool->data = ggc_realloc (cpool->data,
64                                  sizeof(union cpool_entry) * cpool->capacity);
65
66       /* Make sure GC never sees uninitialized tag values.  */
67       memset (cpool->tags + old_cap, 0, cpool->capacity - old_cap);
68       memset (cpool->data + old_cap, 0,
69               (cpool->capacity - old_cap) * sizeof (union cpool_entry));
70     }
71   if (index >= cpool->count)
72     cpool->count = index + 1;
73   cpool->tags[index] = tag;
74   cpool->data[index].w = value;
75 }
76
77 /* Find (or create) a constant pool entry matching TAG and VALUE. */
78
79 int
80 find_constant1 (CPool *cpool, int tag, jword value)
81 {
82   int i;
83   for (i = cpool->count;  --i > 0; )
84     {
85       if (cpool->tags[i] == tag && cpool->data[i].w == value)
86         return i;
87     }
88   i = cpool->count == 0 ? 1 : cpool->count;
89   set_constant_entry (cpool, i, tag, value);
90   return i;
91 }
92
93 /* Find a double-word constant pool entry matching TAG and WORD1/WORD2. */
94
95 int
96 find_constant2 (CPool *cpool, int tag, jword word1, jword word2)
97 {
98   int i;
99   for (i = cpool->count - 1;  --i > 0; )
100     {
101       if (cpool->tags[i] == tag
102           && cpool->data[i].w == word1
103           && cpool->data[i+1].w == word2)
104         return i;
105     }
106   i = cpool->count == 0 ? 1 : cpool->count;
107   set_constant_entry (cpool, i, tag, word1);
108   set_constant_entry (cpool, i+1, 0, word2);
109   return i;
110 }
111
112 static int
113 find_tree_constant (CPool *cpool, int tag, tree value)
114 {
115   int i;
116   for (i = cpool->count;  --i > 0; )
117     {
118       if (cpool->tags[i] == tag && cpool->data[i].t == value)
119         return i;
120     }
121   i = cpool->count == 0 ? 1 : cpool->count;
122   set_constant_entry (cpool, i, tag, 0);
123   cpool->data[i].t = value;
124   return i;
125 }
126
127
128 int
129 find_utf8_constant (CPool *cpool, tree name)
130 {
131   if (name == NULL_TREE)
132     return 0;
133   return find_tree_constant (cpool, CONSTANT_Utf8, name);
134 }
135
136 static int
137 find_class_or_string_constant (CPool *cpool, int tag, tree name)
138 {
139   jword j = find_utf8_constant (cpool, name);
140   int i;
141   for (i = cpool->count;  --i > 0; )
142     {
143       if (cpool->tags[i] == tag && cpool->data[i].w == j)
144         return i;
145     }
146   i = cpool->count;
147   set_constant_entry (cpool, i, tag, j);
148   return i;
149 }
150
151 int
152 find_class_constant (CPool *cpool, tree type)
153 {
154   return find_class_or_string_constant (cpool, CONSTANT_Class,
155                                         build_internal_class_name (type));
156 }
157
158 /* Allocate a CONSTANT_string entry given a STRING_CST. */
159
160 int
161 find_string_constant (CPool *cpool, tree string)
162 {
163   string = get_identifier (TREE_STRING_POINTER (string));
164   return find_class_or_string_constant (cpool, CONSTANT_String, string);
165
166 }
167
168 /* Find (or create) a CONSTANT_NameAndType matching NAME and TYPE.
169    Return its index in the constant pool CPOOL. */
170
171 static int
172 find_name_and_type_constant (CPool *cpool, tree name, tree type)
173 {
174   int name_index = find_utf8_constant (cpool, name);
175   int type_index = find_utf8_constant (cpool, build_java_signature (type));
176   return find_constant1 (cpool, CONSTANT_NameAndType,
177                          (name_index << 16) | type_index);
178 }
179
180 /* Find (or create) a CONSTANT_Fieldref for DECL (a FIELD_DECL or VAR_DECL).
181    Return its index in the constant pool CPOOL. */
182
183 int
184 find_fieldref_index (CPool *cpool, tree decl)
185 {
186   int class_index = find_class_constant (cpool, DECL_CONTEXT (decl));
187   int name_type_index
188     = find_name_and_type_constant (cpool, DECL_NAME (decl), TREE_TYPE (decl));
189   return find_constant1 (cpool, CONSTANT_Fieldref,
190                          (class_index << 16) | name_type_index);
191 }
192
193 /* Find (or create) a CONSTANT_Methodref for DECL (a FUNCTION_DECL).
194    Return its index in the constant pool CPOOL. */
195
196 int
197 find_methodref_index (CPool *cpool, tree decl)
198 {
199   return find_methodref_with_class_index (cpool, decl, DECL_CONTEXT (decl));
200 }
201
202 int
203 find_methodref_with_class_index (CPool *cpool, tree decl, tree mclass)
204 {
205   int class_index = find_class_constant (cpool, mclass);
206   tree name = DECL_CONSTRUCTOR_P (decl) ? init_identifier_node
207     : DECL_NAME (decl);
208   int name_type_index;
209   name_type_index = 
210       find_name_and_type_constant (cpool, name, TREE_TYPE (decl));
211   return find_constant1 (cpool,
212                          CLASS_INTERFACE (TYPE_NAME (mclass))
213                          ? CONSTANT_InterfaceMethodref
214                          : CONSTANT_Methodref,
215                          (class_index << 16) | name_type_index);
216 }
217
218 #define PUT1(X)  (*ptr++ = (X))
219 #define PUT2(X)  (PUT1((X) >> 8), PUT1(X))
220 #define PUT4(X)  (PUT2((X) >> 16), PUT2(X))
221 #define PUTN(P, N)  (memcpy(ptr, (P), (N)), ptr += (N))
222
223 /* Give the number of bytes needed in a .class file for the CPOOL
224    constant pool.  Includes the 2-byte constant_pool_count. */
225
226 int
227 count_constant_pool_bytes (CPool *cpool)
228 {
229   int size = 2;
230   int i = 1;
231   for ( ;  i < cpool->count;  i++)
232     {
233       size++;
234       switch (cpool->tags[i])
235         {
236         case CONSTANT_NameAndType:
237         case CONSTANT_Fieldref:
238         case CONSTANT_Methodref:
239         case CONSTANT_InterfaceMethodref:
240         case CONSTANT_Float:
241         case CONSTANT_Integer:
242           size += 4;
243           break;
244         case CONSTANT_Class:
245         case CONSTANT_String:
246           size += 2;
247           break;
248         case CONSTANT_Long:
249         case CONSTANT_Double:
250           size += 8;
251           i++;
252           break;
253         case CONSTANT_Utf8:
254           {
255             tree t = cpool->data[i].t;
256             int len = IDENTIFIER_LENGTH (t);
257             size += len + 2;
258           }
259           break;
260         default:
261           /* Second word of CONSTANT_Long and  CONSTANT_Double. */
262           size--;
263         }
264     }
265   return size;
266 }
267
268 /* Write the constant pool CPOOL into BUFFER.
269    The length of BUFFER is LENGTH, which must match the needed length. */
270
271 void
272 write_constant_pool (CPool *cpool, unsigned char *buffer, int length)
273 {
274   unsigned char *ptr = buffer;
275   int i = 1;
276   union cpool_entry *datap = &cpool->data[1];
277   PUT2 (cpool->count);
278   for ( ;  i < cpool->count;  i++, datap++)
279     {
280       int tag = cpool->tags[i];
281       PUT1 (tag);
282       switch (tag)
283         {
284         case CONSTANT_NameAndType:
285         case CONSTANT_Fieldref:
286         case CONSTANT_Methodref:
287         case CONSTANT_InterfaceMethodref:
288         case CONSTANT_Float:
289         case CONSTANT_Integer:
290           PUT4 (datap->w);
291           break;
292         case CONSTANT_Class:
293         case CONSTANT_String:
294           PUT2 (datap->w);
295           break;
296           break;
297         case CONSTANT_Long:
298         case CONSTANT_Double:
299           PUT4(datap->w);
300           i++;
301           datap++;
302           PUT4 (datap->w);
303           break;
304         case CONSTANT_Utf8:
305           {
306             tree t = datap->t;
307             int len = IDENTIFIER_LENGTH (t);
308             PUT2 (len);
309             PUTN (IDENTIFIER_POINTER (t), len);
310           }
311           break;
312         }
313     }
314
315   if (ptr != buffer + length)
316     abort ();
317 }
318
319 static GTY(()) tree tag_nodes[13];
320 static tree
321 get_tag_node (int tag)
322 {
323   /* A Cache for build_int_2 (CONSTANT_XXX, 0). */
324
325   if (tag_nodes[tag] == NULL_TREE)
326     tag_nodes[tag] = build_int_2 (tag, 0);
327   return tag_nodes[tag];
328 }
329
330 /* Given a class, return its constant pool, creating one if necessary.  */
331
332 static CPool *
333 cpool_for_class (tree class)
334 {
335   CPool *cpool = TYPE_CPOOL (class);
336
337   if (cpool == NULL)
338     {
339       cpool = ggc_alloc_cleared (sizeof (struct CPool));
340       TYPE_CPOOL (class) = cpool;
341     }
342   return cpool;
343 }
344
345 /* Look for a constant pool entry that matches TAG and NAME.
346    Creates a new entry if not found.
347    TAG is one of CONSTANT_Utf8, CONSTANT_String or CONSTANT_Class.
348    NAME is an IDENTIFIER_NODE naming the Utf8 constant, string, or class.
349    Returns the index of the entry. */
350
351 int
352 alloc_name_constant (int tag, tree name)
353 {
354   CPool *outgoing_cpool = cpool_for_class (output_class);
355   return find_tree_constant (outgoing_cpool, tag, name);
356 }
357
358 /* Build an identifier for the internal name of reference type TYPE. */
359
360 tree
361 build_internal_class_name (tree type)
362 {
363   tree name;
364   if (TYPE_ARRAY_P (type))
365     name = build_java_signature (type);
366   else
367     {
368       name = TYPE_NAME (type);
369       if (TREE_CODE (name) != IDENTIFIER_NODE)
370         name = DECL_NAME (name);
371       name = identifier_subst (name, "", '.', '/', "");
372     }
373   return name;
374 }
375
376 /* Look for a CONSTANT_Class entry for CLAS, creating a new one if needed. */
377
378 int
379 alloc_class_constant (tree clas)
380 {
381   tree class_name = build_internal_class_name (clas);
382   
383   return alloc_name_constant (CONSTANT_Class,
384                               (unmangle_classname 
385                                (IDENTIFIER_POINTER(class_name),
386                                 IDENTIFIER_LENGTH(class_name))));
387 }
388
389 /* Return a reference to the data array of the current constant pool. */
390
391 static tree
392 build_constant_data_ref (void)
393 {
394   tree cpool_data_ref = NULL_TREE;
395
396   if (TYPE_CPOOL_DATA_REF (output_class))
397     cpool_data_ref = TYPE_CPOOL_DATA_REF (output_class);
398
399   if (cpool_data_ref == NULL_TREE)
400     {
401       tree decl;
402       tree decl_name = mangled_classname ("_CD_", output_class);
403       decl = build_decl (VAR_DECL, decl_name,
404                          build_array_type (ptr_type_node,
405                                            one_elt_array_domain_type));
406       TREE_STATIC (decl) = 1;
407       make_decl_rtl (decl, NULL);
408       TYPE_CPOOL_DATA_REF (output_class) = cpool_data_ref
409         = build1 (ADDR_EXPR, ptr_type_node, decl);
410     }
411   return cpool_data_ref;
412 }
413
414 /* Get the pointer value at the INDEX'th element of the constant pool. */
415
416 tree
417 build_ref_from_constant_pool (int index)
418 {
419   tree t = build_constant_data_ref ();
420   index *= int_size_in_bytes (ptr_type_node);
421   t = fold (build (PLUS_EXPR, ptr_type_node,
422                               t, build_int_2 (index, 0)));
423   return build1 (INDIRECT_REF, ptr_type_node, t);
424 }
425
426 /* Build an initializer for the constants field of the current constant pool.
427    Should only be called at top-level, since it may emit declarations. */
428
429 tree
430 build_constants_constructor (void)
431 {
432   CPool *outgoing_cpool = cpool_for_class (current_class);
433   tree tags_value, data_value;
434   tree cons;
435   tree tags_list = NULL_TREE;
436   tree data_list = NULL_TREE;
437   int i;
438   for (i = outgoing_cpool->count;  --i > 0; )
439     {
440       tags_list
441         = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
442                      tags_list);
443       data_list
444         = tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t),
445                      data_list);
446     }
447   if (outgoing_cpool->count > 0)
448     {
449       tree index_type;
450       tree data_decl, tags_decl, tags_type;
451       tree max_index = build_int_2 (outgoing_cpool->count - 1, 0);
452       TREE_TYPE (max_index) = sizetype;
453       index_type = build_index_type (max_index);
454
455       /* Add dummy 0'th element of constant pool. */
456       tags_list = tree_cons (NULL_TREE, get_tag_node (0), tags_list);
457       data_list = tree_cons (NULL_TREE, null_pointer_node, data_list);
458   
459       data_decl = TREE_OPERAND (build_constant_data_ref (), 0);
460       TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type), 
461       DECL_INITIAL (data_decl) = build_constructor (TREE_TYPE (data_decl),
462                                                     data_list);
463       DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
464       DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl));
465       rest_of_decl_compilation (data_decl, (char *) 0, 1, 0);
466       data_value = build_address_of (data_decl);
467
468       tags_type = build_array_type (unsigned_byte_type_node, index_type);
469       tags_decl = build_decl (VAR_DECL, mangled_classname ("_CT_", 
470                                                            current_class),
471                               tags_type);
472       TREE_STATIC (tags_decl) = 1;
473       DECL_INITIAL (tags_decl) = build_constructor (tags_type, tags_list);
474       rest_of_decl_compilation (tags_decl, (char*) 0, 1, 0);
475       tags_value = build_address_of (tags_decl);
476     }
477   else
478     {
479       data_value = null_pointer_node;
480       tags_value = null_pointer_node;
481     }
482   START_RECORD_CONSTRUCTOR (cons, constants_type_node);
483   PUSH_FIELD_VALUE (cons, "size", build_int_2 (outgoing_cpool->count, 0));
484   PUSH_FIELD_VALUE (cons, "tags", tags_value);
485   PUSH_FIELD_VALUE (cons, "data", data_value);
486   FINISH_RECORD_CONSTRUCTOR (cons);
487   return cons;
488 }
489
490 #include "gt-java-constants.h"