]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/java/constants.c
Merge tree-ssa-20020619-branch into mainline.
[thirdparty/gcc.git] / gcc / java / constants.c
CommitLineData
e04a16fb 1/* Handle the constant pool of the Java(TM) Virtual Machine.
85194ee9 2 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
e04a16fb 3
f309ff0a 4This file is part of GCC.
e04a16fb 5
f309ff0a 6GCC is free software; you can redistribute it and/or modify
e04a16fb
AG
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
f309ff0a 11GCC is distributed in the hope that it will be useful,
e04a16fb
AG
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15You should have received a copy of the GNU General Public License
f309ff0a 16along with GCC; see the file COPYING. If not, write to
e04a16fb
AG
17the Free Software Foundation, 59 Temple Place - Suite 330,
18Boston, MA 02111-1307, USA.
19
20Java and all Java-based marks are trademarks or registered trademarks
21of Sun Microsystems, Inc. in the United States and other countries.
22The Free Software Foundation is independent of Sun Microsystems, Inc. */
23
24#include "config.h"
1f43f4b4 25#include "system.h"
4977bab6
ZW
26#include "coretypes.h"
27#include "tm.h"
4bcde32e 28#include "jcf.h"
e04a16fb
AG
29#include "tree.h"
30#include "java-tree.h"
1f43f4b4 31#include "toplev.h"
19e223db 32#include "ggc.h"
e04a16fb 33
d2097937 34static void set_constant_entry (CPool *, int, int, jword);
17211ab5 35static int find_tree_constant (CPool *, int, tree);
d2097937
KG
36static int find_class_or_string_constant (CPool *, int, tree);
37static int find_name_and_type_constant (CPool *, tree, tree);
38static tree get_tag_node (int);
39static tree build_constant_data_ref (void);
75182467 40static CPool *cpool_for_class (tree);
4bcde32e 41
e04a16fb
AG
42/* Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. */
43
4bcde32e 44static void
0a2f0c54 45set_constant_entry (CPool *cpool, int index, int tag, jword value)
e04a16fb
AG
46{
47 if (cpool->data == NULL)
48 {
49 cpool->capacity = 100;
0f0ff6ec
TT
50 cpool->tags = ggc_alloc_cleared (sizeof(uint8) * cpool->capacity);
51 cpool->data = ggc_alloc_cleared (sizeof(union cpool_entry)
52 * cpool->capacity);
e04a16fb
AG
53 cpool->count = 1;
54 }
55 if (index >= cpool->capacity)
56 {
0f0ff6ec 57 int old_cap = cpool->capacity;
e04a16fb
AG
58 cpool->capacity *= 2;
59 if (index >= cpool->capacity)
60 cpool->capacity = index + 10;
17211ab5
GK
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);
0f0ff6ec
TT
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));
e04a16fb
AG
70 }
71 if (index >= cpool->count)
72 cpool->count = index + 1;
73 cpool->tags[index] = tag;
17211ab5 74 cpool->data[index].w = value;
e04a16fb
AG
75}
76
77/* Find (or create) a constant pool entry matching TAG and VALUE. */
78
79int
0a2f0c54 80find_constant1 (CPool *cpool, int tag, jword value)
e04a16fb
AG
81{
82 int i;
83 for (i = cpool->count; --i > 0; )
84 {
17211ab5 85 if (cpool->tags[i] == tag && cpool->data[i].w == value)
e04a16fb
AG
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
95int
0a2f0c54 96find_constant2 (CPool *cpool, int tag, jword word1, jword word2)
e04a16fb
AG
97{
98 int i;
99 for (i = cpool->count - 1; --i > 0; )
100 {
101 if (cpool->tags[i] == tag
17211ab5
GK
102 && cpool->data[i].w == word1
103 && cpool->data[i+1].w == word2)
e04a16fb
AG
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
17211ab5 112static int
0a2f0c54 113find_tree_constant (CPool *cpool, int tag, tree value)
17211ab5
GK
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
e04a16fb 128int
0a2f0c54 129find_utf8_constant (CPool *cpool, tree name)
e04a16fb
AG
130{
131 if (name == NULL_TREE)
132 return 0;
17211ab5 133 return find_tree_constant (cpool, CONSTANT_Utf8, name);
e04a16fb
AG
134}
135
4bcde32e 136static int
0a2f0c54 137find_class_or_string_constant (CPool *cpool, int tag, tree name)
e04a16fb 138{
17211ab5 139 jword j = find_utf8_constant (cpool, name);
e04a16fb
AG
140 int i;
141 for (i = cpool->count; --i > 0; )
142 {
17211ab5 143 if (cpool->tags[i] == tag && cpool->data[i].w == j)
e04a16fb
AG
144 return i;
145 }
146 i = cpool->count;
17211ab5 147 set_constant_entry (cpool, i, tag, j);
e04a16fb
AG
148 return i;
149}
150
151int
0a2f0c54 152find_class_constant (CPool *cpool, tree type)
e04a16fb
AG
153{
154 return find_class_or_string_constant (cpool, CONSTANT_Class,
155 build_internal_class_name (type));
156}
157
d640220c
PB
158/* Allocate a CONSTANT_string entry given a STRING_CST. */
159
160int
0a2f0c54 161find_string_constant (CPool *cpool, tree string)
d640220c
PB
162{
163 string = get_identifier (TREE_STRING_POINTER (string));
164 return find_class_or_string_constant (cpool, CONSTANT_String, string);
165
166}
167
e04a16fb
AG
168/* Find (or create) a CONSTANT_NameAndType matching NAME and TYPE.
169 Return its index in the constant pool CPOOL. */
170
4bcde32e 171static int
0a2f0c54 172find_name_and_type_constant (CPool *cpool, tree name, tree type)
e04a16fb
AG
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
183int
0a2f0c54 184find_fieldref_index (CPool *cpool, tree decl)
e04a16fb
AG
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
196int
0a2f0c54 197find_methodref_index (CPool *cpool, tree decl)
e04a16fb 198{
8789b9fa
PB
199 return find_methodref_with_class_index (cpool, decl, DECL_CONTEXT (decl));
200}
201
202int
0a2f0c54 203find_methodref_with_class_index (CPool *cpool, tree decl, tree mclass)
8789b9fa 204{
72a0aac6 205 int class_index = find_class_constant (cpool, mclass);
e04a16fb
AG
206 tree name = DECL_CONSTRUCTOR_P (decl) ? init_identifier_node
207 : DECL_NAME (decl);
48aedbca 208 int name_type_index;
48aedbca
AG
209 name_type_index =
210 find_name_and_type_constant (cpool, name, TREE_TYPE (decl));
72a0aac6
PB
211 return find_constant1 (cpool,
212 CLASS_INTERFACE (TYPE_NAME (mclass))
213 ? CONSTANT_InterfaceMethodref
214 : CONSTANT_Methodref,
e04a16fb
AG
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))
cb9b7a8c 221#define PUTN(P, N) (memcpy(ptr, (P), (N)), ptr += (N))
e04a16fb
AG
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
226int
0a2f0c54 227count_constant_pool_bytes (CPool *cpool)
e04a16fb
AG
228{
229 int size = 2;
230 int i = 1;
d640220c 231 for ( ; i < cpool->count; i++)
e04a16fb
AG
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:
d640220c
PB
250 size += 8;
251 i++;
e04a16fb
AG
252 break;
253 case CONSTANT_Utf8:
254 {
17211ab5 255 tree t = cpool->data[i].t;
e04a16fb
AG
256 int len = IDENTIFIER_LENGTH (t);
257 size += len + 2;
258 }
259 break;
d640220c
PB
260 default:
261 /* Second word of CONSTANT_Long and CONSTANT_Double. */
262 size--;
e04a16fb
AG
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
271void
0a2f0c54 272write_constant_pool (CPool *cpool, unsigned char *buffer, int length)
e04a16fb 273{
400500c4 274 unsigned char *ptr = buffer;
e04a16fb 275 int i = 1;
17211ab5 276 union cpool_entry *datap = &cpool->data[1];
e04a16fb
AG
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:
17211ab5 290 PUT4 (datap->w);
e04a16fb
AG
291 break;
292 case CONSTANT_Class:
293 case CONSTANT_String:
17211ab5 294 PUT2 (datap->w);
e04a16fb
AG
295 break;
296 break;
297 case CONSTANT_Long:
298 case CONSTANT_Double:
17211ab5 299 PUT4(datap->w);
e04a16fb
AG
300 i++;
301 datap++;
17211ab5 302 PUT4 (datap->w);
e04a16fb
AG
303 break;
304 case CONSTANT_Utf8:
305 {
17211ab5 306 tree t = datap->t;
e04a16fb
AG
307 int len = IDENTIFIER_LENGTH (t);
308 PUT2 (len);
309 PUTN (IDENTIFIER_POINTER (t), len);
310 }
311 break;
312 }
313 }
400500c4 314
e04a16fb 315 if (ptr != buffer + length)
400500c4 316 abort ();
e04a16fb
AG
317}
318
e2500fed 319static GTY(()) tree tag_nodes[13];
4bcde32e 320static tree
0a2f0c54 321get_tag_node (int tag)
e04a16fb 322{
19e223db 323 /* A Cache for build_int_2 (CONSTANT_XXX, 0). */
19e223db 324
e04a16fb 325 if (tag_nodes[tag] == NULL_TREE)
1f8f4a0b 326 tag_nodes[tag] = build_int_2 (tag, 0);
e04a16fb
AG
327 return tag_nodes[tag];
328}
329
75182467
JS
330/* Given a class, return its constant pool, creating one if necessary. */
331
332static CPool *
333cpool_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
e04a16fb
AG
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
351int
0a2f0c54 352alloc_name_constant (int tag, tree name)
e04a16fb 353{
85194ee9 354 CPool *outgoing_cpool = cpool_for_class (output_class);
17211ab5 355 return find_tree_constant (outgoing_cpool, tag, name);
e04a16fb
AG
356}
357
358/* Build an identifier for the internal name of reference type TYPE. */
359
360tree
0a2f0c54 361build_internal_class_name (tree type)
e04a16fb
AG
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
378int
0a2f0c54 379alloc_class_constant (tree clas)
e04a16fb 380{
7e57923c
AH
381 tree class_name = build_internal_class_name (clas);
382
e04a16fb 383 return alloc_name_constant (CONSTANT_Class,
7e57923c
AH
384 (unmangle_classname
385 (IDENTIFIER_POINTER(class_name),
386 IDENTIFIER_LENGTH(class_name))));
e04a16fb
AG
387}
388
6de9cd9a 389/* Return the decl of the data array of the current constant pool. */
e04a16fb 390
4bcde32e 391static tree
0a2f0c54 392build_constant_data_ref (void)
e04a16fb 393{
6de9cd9a 394 tree decl = TYPE_CPOOL_DATA_REF (output_class);
d3ab697b 395
6de9cd9a 396 if (decl == NULL_TREE)
e04a16fb 397 {
6de9cd9a 398 tree type;
85194ee9 399 tree decl_name = mangled_classname ("_CD_", output_class);
6de9cd9a
DN
400
401 /* Build a type with unspecified bounds. The will make sure
402 that targets do the right thing with whatever size we end
403 up with at the end. Using bounds that are too small risks
404 assuming the data is in the small data section. */
405 type = build_array_type (ptr_type_node, NULL_TREE);
406
407 /* We need to lay out the type ourselves, since build_array_type
408 thinks the type is incomplete. */
409 layout_type (type);
410
411 decl = build_decl (VAR_DECL, decl_name, type);
e04a16fb 412 TREE_STATIC (decl) = 1;
6c418184 413 make_decl_rtl (decl, NULL);
6de9cd9a 414 TYPE_CPOOL_DATA_REF (output_class) = decl;
e04a16fb 415 }
6de9cd9a
DN
416
417 return decl;
e04a16fb
AG
418}
419
420/* Get the pointer value at the INDEX'th element of the constant pool. */
421
422tree
0a2f0c54 423build_ref_from_constant_pool (int index)
e04a16fb 424{
6de9cd9a
DN
425 tree d = build_constant_data_ref ();
426 tree i = build_int_2 (index, 0);
427 return build (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i);
e04a16fb
AG
428}
429
634661fe 430/* Build an initializer for the constants field of the current constant pool.
e04a16fb
AG
431 Should only be called at top-level, since it may emit declarations. */
432
433tree
0a2f0c54 434build_constants_constructor (void)
e04a16fb 435{
75182467 436 CPool *outgoing_cpool = cpool_for_class (current_class);
e04a16fb
AG
437 tree tags_value, data_value;
438 tree cons;
439 tree tags_list = NULL_TREE;
440 tree data_list = NULL_TREE;
441 int i;
442 for (i = outgoing_cpool->count; --i > 0; )
443 {
444 tags_list
445 = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
446 tags_list);
447 data_list
17211ab5 448 = tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t),
e04a16fb
AG
449 data_list);
450 }
451 if (outgoing_cpool->count > 0)
452 {
453 tree index_type;
454 tree data_decl, tags_decl, tags_type;
455 tree max_index = build_int_2 (outgoing_cpool->count - 1, 0);
456 TREE_TYPE (max_index) = sizetype;
457 index_type = build_index_type (max_index);
458
459 /* Add dummy 0'th element of constant pool. */
460 tags_list = tree_cons (NULL_TREE, get_tag_node (0), tags_list);
461 data_list = tree_cons (NULL_TREE, null_pointer_node, data_list);
462
6de9cd9a 463 data_decl = build_constant_data_ref ();
e04a16fb 464 TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type),
dcf92453
ZW
465 DECL_INITIAL (data_decl) = build_constructor (TREE_TYPE (data_decl),
466 data_list);
e04a16fb 467 DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
06ceef4e
RK
468 DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl));
469 rest_of_decl_compilation (data_decl, (char *) 0, 1, 0);
e04a16fb
AG
470 data_value = build_address_of (data_decl);
471
472 tags_type = build_array_type (unsigned_byte_type_node, index_type);
473 tags_decl = build_decl (VAR_DECL, mangled_classname ("_CT_",
474 current_class),
475 tags_type);
476 TREE_STATIC (tags_decl) = 1;
dcf92453 477 DECL_INITIAL (tags_decl) = build_constructor (tags_type, tags_list);
e04a16fb
AG
478 rest_of_decl_compilation (tags_decl, (char*) 0, 1, 0);
479 tags_value = build_address_of (tags_decl);
480 }
481 else
482 {
483 data_value = null_pointer_node;
484 tags_value = null_pointer_node;
485 }
486 START_RECORD_CONSTRUCTOR (cons, constants_type_node);
487 PUSH_FIELD_VALUE (cons, "size", build_int_2 (outgoing_cpool->count, 0));
488 PUSH_FIELD_VALUE (cons, "tags", tags_value);
489 PUSH_FIELD_VALUE (cons, "data", data_value);
490 FINISH_RECORD_CONSTRUCTOR (cons);
491 return cons;
492}
e2500fed
GK
493
494#include "gt-java-constants.h"