xref: /openbsd/gnu/usr.bin/gcc/gcc/java/constants.c (revision c87b03e5)
1 /* Handle the constant pool of the Java(TM) Virtual Machine.
2    Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3 
4 This file is part of GNU CC.
5 
6 GNU CC 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 GNU CC 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 GNU CC; 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 "jcf.h"
27 #include "tree.h"
28 #include "java-tree.h"
29 #include "toplev.h"
30 #include "ggc.h"
31 
32 static void set_constant_entry PARAMS ((CPool *, int, int, jword));
33 static int find_class_or_string_constant PARAMS ((CPool *, int, tree));
34 static int find_name_and_type_constant PARAMS ((CPool *, tree, tree));
35 static tree get_tag_node PARAMS ((int));
36 static tree build_constant_data_ref PARAMS ((void));
37 
38 /* Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. */
39 
40 static void
set_constant_entry(cpool,index,tag,value)41 set_constant_entry (cpool, index, tag, value)
42      CPool *cpool;
43      int index;
44      int tag;
45      jword value;
46 {
47   if (cpool->data == NULL)
48     {
49       cpool->capacity = 100;
50       cpool->tags = xmalloc (sizeof(uint8) * cpool->capacity);
51       cpool->data = xmalloc (sizeof(jword) * cpool->capacity);
52       cpool->count = 1;
53     }
54   if (index >= cpool->capacity)
55     {
56       cpool->capacity *= 2;
57       if (index >= cpool->capacity)
58 	cpool->capacity = index + 10;
59       cpool->tags = xrealloc (cpool->tags, sizeof(uint8) * cpool->capacity);
60       cpool->data = xrealloc (cpool->data, sizeof(jword) * cpool->capacity);
61     }
62   if (index >= cpool->count)
63     cpool->count = index + 1;
64   cpool->tags[index] = tag;
65   cpool->data[index] = value;
66 }
67 
68 /* Find (or create) a constant pool entry matching TAG and VALUE. */
69 
70 int
find_constant1(cpool,tag,value)71 find_constant1 (cpool, tag, value)
72      CPool *cpool;
73      int tag;
74      jword value;
75 {
76   int i;
77   for (i = cpool->count;  --i > 0; )
78     {
79       if (cpool->tags[i] == tag && cpool->data[i] == value)
80 	return i;
81     }
82   i = cpool->count == 0 ? 1 : cpool->count;
83   set_constant_entry (cpool, i, tag, value);
84   return i;
85 }
86 
87 /* Find a double-word constant pool entry matching TAG and WORD1/WORD2. */
88 
89 int
find_constant2(cpool,tag,word1,word2)90 find_constant2 (cpool, tag, word1, word2)
91      CPool *cpool;
92      int tag;
93      jword word1, word2;
94 {
95   int i;
96   for (i = cpool->count - 1;  --i > 0; )
97     {
98       if (cpool->tags[i] == tag
99 	  && cpool->data[i] == word1
100 	  && cpool->data[i+1] == word2)
101 	return i;
102     }
103   i = cpool->count == 0 ? 1 : cpool->count;
104   set_constant_entry (cpool, i, tag, word1);
105   set_constant_entry (cpool, i+1, 0, word2);
106   return i;
107 }
108 
109 int
find_utf8_constant(cpool,name)110 find_utf8_constant (cpool, name)
111      CPool *cpool;
112      tree name;
113 {
114   if (name == NULL_TREE)
115     return 0;
116   return find_constant1 (cpool, CONSTANT_Utf8, (jword) name);
117 }
118 
119 static int
find_class_or_string_constant(cpool,tag,name)120 find_class_or_string_constant (cpool, tag, name)
121      CPool *cpool;
122      int tag;
123      tree name;
124 {
125   int j = find_utf8_constant (cpool, name);
126   int i;
127   for (i = cpool->count;  --i > 0; )
128     {
129       if (cpool->tags[i] == tag && cpool->data[i] == (jword) j)
130 	return i;
131     }
132   i = cpool->count;
133   set_constant_entry (cpool, i, tag, (jword) j);
134   return i;
135 }
136 
137 int
find_class_constant(cpool,type)138 find_class_constant (cpool, type)
139      CPool *cpool;
140      tree type;
141 {
142   return find_class_or_string_constant (cpool, CONSTANT_Class,
143 					build_internal_class_name (type));
144 }
145 
146 /* Allocate a CONSTANT_string entry given a STRING_CST. */
147 
148 int
find_string_constant(cpool,string)149 find_string_constant (cpool, string)
150      CPool *cpool;
151      tree string;
152 {
153   string = get_identifier (TREE_STRING_POINTER (string));
154   return find_class_or_string_constant (cpool, CONSTANT_String, string);
155 
156 }
157 
158 /* Find (or create) a CONSTANT_NameAndType matching NAME and TYPE.
159    Return its index in the constant pool CPOOL. */
160 
161 static int
find_name_and_type_constant(cpool,name,type)162 find_name_and_type_constant (cpool, name, type)
163      CPool *cpool;
164      tree name;
165      tree type;
166 {
167   int name_index = find_utf8_constant (cpool, name);
168   int type_index = find_utf8_constant (cpool, build_java_signature (type));
169   return find_constant1 (cpool, CONSTANT_NameAndType,
170 			 (name_index << 16) | type_index);
171 }
172 
173 /* Find (or create) a CONSTANT_Fieldref for DECL (a FIELD_DECL or VAR_DECL).
174    Return its index in the constant pool CPOOL. */
175 
176 int
find_fieldref_index(cpool,decl)177 find_fieldref_index (cpool, decl)
178      CPool *cpool;
179      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
find_methodref_index(cpool,decl)192 find_methodref_index (cpool, decl)
193      CPool *cpool;
194      tree decl;
195 {
196   return find_methodref_with_class_index (cpool, decl, DECL_CONTEXT (decl));
197 }
198 
199 int
find_methodref_with_class_index(cpool,decl,mclass)200 find_methodref_with_class_index (cpool, decl, mclass)
201      CPool *cpool;
202      tree decl;
203      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
count_constant_pool_bytes(cpool)227 count_constant_pool_bytes (cpool)
228      CPool *cpool;
229 {
230   int size = 2;
231   int i = 1;
232   for ( ;  i < cpool->count;  i++)
233     {
234       size++;
235       switch (cpool->tags[i])
236 	{
237 	case CONSTANT_NameAndType:
238 	case CONSTANT_Fieldref:
239 	case CONSTANT_Methodref:
240 	case CONSTANT_InterfaceMethodref:
241 	case CONSTANT_Float:
242 	case CONSTANT_Integer:
243 	  size += 4;
244 	  break;
245 	case CONSTANT_Class:
246 	case CONSTANT_String:
247 	  size += 2;
248 	  break;
249 	case CONSTANT_Long:
250 	case CONSTANT_Double:
251 	  size += 8;
252 	  i++;
253 	  break;
254 	case CONSTANT_Utf8:
255 	  {
256 	    tree t = (tree) cpool->data[i];
257 	    int len = IDENTIFIER_LENGTH (t);
258 	    size += len + 2;
259 	  }
260 	  break;
261 	default:
262 	  /* Second word of CONSTANT_Long and  CONSTANT_Double. */
263 	  size--;
264 	}
265     }
266   return size;
267 }
268 
269 /* Write the constant pool CPOOL into BUFFER.
270    The length of BUFFER is LENGTH, which must match the needed length. */
271 
272 void
write_constant_pool(cpool,buffer,length)273 write_constant_pool (cpool, buffer, length)
274      CPool *cpool;
275      unsigned char *buffer;
276      int length;
277 {
278   unsigned char *ptr = buffer;
279   int i = 1;
280   jword *datap = &cpool->data[1];
281   PUT2 (cpool->count);
282   for ( ;  i < cpool->count;  i++, datap++)
283     {
284       int tag = cpool->tags[i];
285       PUT1 (tag);
286       switch (tag)
287 	{
288 	case CONSTANT_NameAndType:
289 	case CONSTANT_Fieldref:
290 	case CONSTANT_Methodref:
291 	case CONSTANT_InterfaceMethodref:
292 	case CONSTANT_Float:
293 	case CONSTANT_Integer:
294 	  PUT4 (*datap);
295 	  break;
296 	case CONSTANT_Class:
297 	case CONSTANT_String:
298 	  PUT2 (*datap);
299 	  break;
300 	  break;
301 	case CONSTANT_Long:
302 	case CONSTANT_Double:
303 	  PUT4(*datap);
304 	  i++;
305 	  datap++;
306 	  PUT4 (*datap);
307 	  break;
308 	case CONSTANT_Utf8:
309 	  {
310 	    tree t = (tree) *datap;
311 	    int len = IDENTIFIER_LENGTH (t);
312 	    PUT2 (len);
313 	    PUTN (IDENTIFIER_POINTER (t), len);
314 	  }
315 	  break;
316 	}
317     }
318 
319   if (ptr != buffer + length)
320     abort ();
321 }
322 
323 CPool *outgoing_cpool;
324 
325 static GTY(()) tree tag_nodes[13];
326 static tree
get_tag_node(tag)327 get_tag_node (tag)
328      int tag;
329 {
330   /* A Cache for build_int_2 (CONSTANT_XXX, 0). */
331 
332   if (tag_nodes[tag] == NULL_TREE)
333     tag_nodes[tag] = build_int_2 (tag, 0);
334   return tag_nodes[tag];
335 }
336 
337 /* Look for a constant pool entry that matches TAG and NAME.
338    Creates a new entry if not found.
339    TAG is one of CONSTANT_Utf8, CONSTANT_String or CONSTANT_Class.
340    NAME is an IDENTIFIER_NODE naming the Utf8 constant, string, or class.
341    Returns the index of the entry. */
342 
343 int
alloc_name_constant(tag,name)344 alloc_name_constant (tag, name)
345      int tag;
346      tree name;
347 {
348   return find_constant1 (outgoing_cpool, tag, (jword) name);
349 }
350 
351 /* Build an identifier for the internal name of reference type TYPE. */
352 
353 tree
build_internal_class_name(type)354 build_internal_class_name (type)
355      tree type;
356 {
357   tree name;
358   if (TYPE_ARRAY_P (type))
359     name = build_java_signature (type);
360   else
361     {
362       name = TYPE_NAME (type);
363       if (TREE_CODE (name) != IDENTIFIER_NODE)
364 	name = DECL_NAME (name);
365       name = identifier_subst (name, "", '.', '/', "");
366     }
367   return name;
368 }
369 
370 /* Look for a CONSTANT_Class entry for CLAS, creating a new one if needed. */
371 
372 int
alloc_class_constant(clas)373 alloc_class_constant (clas)
374      tree clas;
375 {
376   tree class_name = build_internal_class_name (clas);
377 
378   return alloc_name_constant (CONSTANT_Class,
379 			      (unmangle_classname
380 			       (IDENTIFIER_POINTER(class_name),
381 				IDENTIFIER_LENGTH(class_name))));
382 }
383 
384 /* Return a reference to the data array of the current constant pool. */
385 
386 static tree
build_constant_data_ref()387 build_constant_data_ref ()
388 {
389   if (TYPE_CPOOL_DATA_REF (current_class))
390     current_constant_pool_data_ref = TYPE_CPOOL_DATA_REF (current_class);
391 
392   else if (current_constant_pool_data_ref == NULL_TREE)
393     {
394       tree decl;
395       tree decl_name = mangled_classname ("_CD_", current_class);
396       decl = build_decl (VAR_DECL, decl_name,
397 			 build_array_type (ptr_type_node,
398 					   one_elt_array_domain_type));
399       TREE_STATIC (decl) = 1;
400       make_decl_rtl (decl, NULL);
401       TYPE_CPOOL_DATA_REF (current_class) = current_constant_pool_data_ref
402 	= build1 (ADDR_EXPR, ptr_type_node, decl);
403     }
404   return current_constant_pool_data_ref;
405 }
406 
407 /* Get the pointer value at the INDEX'th element of the constant pool. */
408 
409 tree
build_ref_from_constant_pool(index)410 build_ref_from_constant_pool (index)
411      int index;
412 {
413   tree t = build_constant_data_ref ();
414   index *= int_size_in_bytes (ptr_type_node);
415   t = fold (build (PLUS_EXPR, ptr_type_node,
416                               t, build_int_2 (index, 0)));
417   return build1 (INDIRECT_REF, ptr_type_node, t);
418 }
419 
420 /* Build an initializer for the constants field of the current constal pool.
421    Should only be called at top-level, since it may emit declarations. */
422 
423 tree
build_constants_constructor()424 build_constants_constructor ()
425 {
426   tree tags_value, data_value;
427   tree cons;
428   tree tags_list = NULL_TREE;
429   tree data_list = NULL_TREE;
430   int i;
431   for (i = outgoing_cpool->count;  --i > 0; )
432     {
433       tags_list
434 	= tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
435 		     tags_list);
436       data_list
437 	= tree_cons (NULL_TREE, build_utf8_ref ((tree)outgoing_cpool->data[i]),
438 		     data_list);
439     }
440   if (outgoing_cpool->count > 0)
441     {
442       tree index_type;
443       tree data_decl, tags_decl, tags_type;
444       tree max_index = build_int_2 (outgoing_cpool->count - 1, 0);
445       TREE_TYPE (max_index) = sizetype;
446       index_type = build_index_type (max_index);
447 
448       /* Add dummy 0'th element of constant pool. */
449       tags_list = tree_cons (NULL_TREE, get_tag_node (0), tags_list);
450       data_list = tree_cons (NULL_TREE, null_pointer_node, data_list);
451 
452       data_decl = TREE_OPERAND (build_constant_data_ref (), 0);
453       TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type),
454       DECL_INITIAL (data_decl) = build (CONSTRUCTOR, TREE_TYPE (data_decl),
455 					NULL_TREE, data_list);
456       DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
457       DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl));
458       rest_of_decl_compilation (data_decl, (char *) 0, 1, 0);
459       data_value = build_address_of (data_decl);
460 
461       tags_type = build_array_type (unsigned_byte_type_node, index_type);
462       tags_decl = build_decl (VAR_DECL, mangled_classname ("_CT_",
463 							   current_class),
464 			      tags_type);
465       TREE_STATIC (tags_decl) = 1;
466       DECL_INITIAL (tags_decl) = build (CONSTRUCTOR, tags_type,
467 					NULL_TREE, tags_list);
468       rest_of_decl_compilation (tags_decl, (char*) 0, 1, 0);
469       tags_value = build_address_of (tags_decl);
470     }
471   else
472     {
473       data_value = null_pointer_node;
474       tags_value = null_pointer_node;
475     }
476   START_RECORD_CONSTRUCTOR (cons, constants_type_node);
477   PUSH_FIELD_VALUE (cons, "size", build_int_2 (outgoing_cpool->count, 0));
478   PUSH_FIELD_VALUE (cons, "tags", tags_value);
479   PUSH_FIELD_VALUE (cons, "data", data_value);
480   FINISH_RECORD_CONSTRUCTOR (cons);
481   return cons;
482 }
483 
484 #include "gt-java-constants.h"
485