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