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