]>
Commit | Line | Data |
---|---|---|
377029eb | 1 | /* Handle the constant pool of the Java(TM) Virtual Machine. |
f1717362 | 2 | Copyright (C) 1997-2016 Free Software Foundation, Inc. |
377029eb | 3 | |
7d82ed5e | 4 | This file is part of GCC. |
377029eb | 5 | |
7d82ed5e | 6 | GCC is free software; you can redistribute it and/or modify |
377029eb | 7 | it under the terms of the GNU General Public License as published by |
e4b52719 | 8 | the Free Software Foundation; either version 3, or (at your option) |
377029eb | 9 | any later version. |
10 | ||
7d82ed5e | 11 | GCC is distributed in the hope that it will be useful, |
377029eb | 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 | |
e4b52719 | 16 | along with GCC; see the file COPYING3. If not see |
17 | <http://www.gnu.org/licenses/>. | |
377029eb | 18 | |
19 | Java and all Java-based marks are trademarks or registered trademarks | |
20 | of Sun Microsystems, Inc. in the United States and other countries. | |
21 | The Free Software Foundation is independent of Sun Microsystems, Inc. */ | |
22 | ||
23 | #include "config.h" | |
014e6e0c | 24 | #include "system.h" |
805e22b2 | 25 | #include "coretypes.h" |
26 | #include "tm.h" | |
4cba6f60 | 27 | #include "tree.h" |
28 | #include "stringpool.h" | |
003019ba | 29 | #include "jcf.h" |
b20a8bb4 | 30 | #include "fold-const.h" |
9ed99284 | 31 | #include "stor-layout.h" |
377029eb | 32 | #include "java-tree.h" |
014e6e0c | 33 | #include "toplev.h" |
377029eb | 34 | |
6852521a | 35 | static void set_constant_entry (CPool *, int, int, jword); |
573aba85 | 36 | static int find_tree_constant (CPool *, int, tree); |
6852521a | 37 | static int find_name_and_type_constant (CPool *, tree, tree); |
38 | static tree get_tag_node (int); | |
003019ba | 39 | |
377029eb | 40 | /* Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. */ |
41 | ||
003019ba | 42 | static void |
2883a3ed | 43 | set_constant_entry (CPool *cpool, int index, int tag, jword value) |
377029eb | 44 | { |
45 | if (cpool->data == NULL) | |
46 | { | |
47 | cpool->capacity = 100; | |
25a27413 | 48 | cpool->tags = ggc_cleared_vec_alloc<uint8> (cpool->capacity); |
49 | cpool->data = ggc_cleared_vec_alloc<cpool_entry> (cpool->capacity); | |
377029eb | 50 | cpool->count = 1; |
51 | } | |
52 | if (index >= cpool->capacity) | |
53 | { | |
7473cb81 | 54 | int old_cap = cpool->capacity; |
377029eb | 55 | cpool->capacity *= 2; |
56 | if (index >= cpool->capacity) | |
57 | cpool->capacity = index + 10; | |
25a1c410 | 58 | cpool->tags = GGC_RESIZEVEC (uint8, cpool->tags, cpool->capacity); |
59 | cpool->data = GGC_RESIZEVEC (union cpool_entry, cpool->data, | |
60 | cpool->capacity); | |
7473cb81 | 61 | |
62 | /* Make sure GC never sees uninitialized tag values. */ | |
63 | memset (cpool->tags + old_cap, 0, cpool->capacity - old_cap); | |
64 | memset (cpool->data + old_cap, 0, | |
65 | (cpool->capacity - old_cap) * sizeof (union cpool_entry)); | |
377029eb | 66 | } |
67 | if (index >= cpool->count) | |
68 | cpool->count = index + 1; | |
69 | cpool->tags[index] = tag; | |
573aba85 | 70 | cpool->data[index].w = value; |
377029eb | 71 | } |
72 | ||
73 | /* Find (or create) a constant pool entry matching TAG and VALUE. */ | |
74 | ||
75 | int | |
2883a3ed | 76 | find_constant1 (CPool *cpool, int tag, jword value) |
377029eb | 77 | { |
78 | int i; | |
79 | for (i = cpool->count; --i > 0; ) | |
80 | { | |
573aba85 | 81 | if (cpool->tags[i] == tag && cpool->data[i].w == value) |
377029eb | 82 | return i; |
83 | } | |
84 | i = cpool->count == 0 ? 1 : cpool->count; | |
85 | set_constant_entry (cpool, i, tag, value); | |
86 | return i; | |
87 | } | |
88 | ||
89 | /* Find a double-word constant pool entry matching TAG and WORD1/WORD2. */ | |
90 | ||
91 | int | |
2883a3ed | 92 | find_constant2 (CPool *cpool, int tag, jword word1, jword word2) |
377029eb | 93 | { |
94 | int i; | |
95 | for (i = cpool->count - 1; --i > 0; ) | |
96 | { | |
97 | if (cpool->tags[i] == tag | |
573aba85 | 98 | && cpool->data[i].w == word1 |
99 | && cpool->data[i+1].w == word2) | |
377029eb | 100 | return i; |
101 | } | |
102 | i = cpool->count == 0 ? 1 : cpool->count; | |
103 | set_constant_entry (cpool, i, tag, word1); | |
104 | set_constant_entry (cpool, i+1, 0, word2); | |
105 | return i; | |
106 | } | |
107 | ||
573aba85 | 108 | static int |
2883a3ed | 109 | find_tree_constant (CPool *cpool, int tag, tree value) |
573aba85 | 110 | { |
111 | int i; | |
112 | for (i = cpool->count; --i > 0; ) | |
113 | { | |
114 | if (cpool->tags[i] == tag && cpool->data[i].t == value) | |
115 | return i; | |
116 | } | |
117 | i = cpool->count == 0 ? 1 : cpool->count; | |
118 | set_constant_entry (cpool, i, tag, 0); | |
119 | cpool->data[i].t = value; | |
120 | return i; | |
121 | } | |
122 | ||
123 | ||
377029eb | 124 | int |
2883a3ed | 125 | find_utf8_constant (CPool *cpool, tree name) |
377029eb | 126 | { |
127 | if (name == NULL_TREE) | |
128 | return 0; | |
573aba85 | 129 | return find_tree_constant (cpool, CONSTANT_Utf8, name); |
377029eb | 130 | } |
131 | ||
65bf3316 | 132 | int |
2883a3ed | 133 | find_class_or_string_constant (CPool *cpool, int tag, tree name) |
377029eb | 134 | { |
573aba85 | 135 | jword j = find_utf8_constant (cpool, name); |
377029eb | 136 | int i; |
137 | for (i = cpool->count; --i > 0; ) | |
138 | { | |
573aba85 | 139 | if (cpool->tags[i] == tag && cpool->data[i].w == j) |
377029eb | 140 | return i; |
141 | } | |
142 | i = cpool->count; | |
573aba85 | 143 | set_constant_entry (cpool, i, tag, j); |
377029eb | 144 | return i; |
145 | } | |
146 | ||
147 | int | |
2883a3ed | 148 | find_class_constant (CPool *cpool, tree type) |
377029eb | 149 | { |
150 | return find_class_or_string_constant (cpool, CONSTANT_Class, | |
151 | build_internal_class_name (type)); | |
152 | } | |
153 | ||
533bc3bc | 154 | /* Allocate a CONSTANT_string entry given a STRING_CST. */ |
155 | ||
156 | int | |
2883a3ed | 157 | find_string_constant (CPool *cpool, tree string) |
533bc3bc | 158 | { |
159 | string = get_identifier (TREE_STRING_POINTER (string)); | |
160 | return find_class_or_string_constant (cpool, CONSTANT_String, string); | |
161 | ||
162 | } | |
163 | ||
377029eb | 164 | /* Find (or create) a CONSTANT_NameAndType matching NAME and TYPE. |
165 | Return its index in the constant pool CPOOL. */ | |
166 | ||
003019ba | 167 | static int |
2883a3ed | 168 | find_name_and_type_constant (CPool *cpool, tree name, tree type) |
377029eb | 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 | |
2883a3ed | 180 | find_fieldref_index (CPool *cpool, tree decl) |
377029eb | 181 | { |
182 | int class_index = find_class_constant (cpool, DECL_CONTEXT (decl)); | |
183 | int name_type_index | |
184 | = find_name_and_type_constant (cpool, DECL_NAME (decl), TREE_TYPE (decl)); | |
185 | return find_constant1 (cpool, CONSTANT_Fieldref, | |
186 | (class_index << 16) | name_type_index); | |
187 | } | |
188 | ||
189 | /* Find (or create) a CONSTANT_Methodref for DECL (a FUNCTION_DECL). | |
190 | Return its index in the constant pool CPOOL. */ | |
191 | ||
192 | int | |
2883a3ed | 193 | find_methodref_index (CPool *cpool, tree decl) |
377029eb | 194 | { |
735b10df | 195 | return find_methodref_with_class_index (cpool, decl, DECL_CONTEXT (decl)); |
196 | } | |
197 | ||
198 | int | |
2883a3ed | 199 | find_methodref_with_class_index (CPool *cpool, tree decl, tree mclass) |
735b10df | 200 | { |
d9935f38 | 201 | int class_index = find_class_constant (cpool, mclass); |
377029eb | 202 | tree name = DECL_CONSTRUCTOR_P (decl) ? init_identifier_node |
203 | : DECL_NAME (decl); | |
c0c735e9 | 204 | int name_type_index; |
c0c735e9 | 205 | name_type_index = |
206 | find_name_and_type_constant (cpool, name, TREE_TYPE (decl)); | |
d9935f38 | 207 | return find_constant1 (cpool, |
208 | CLASS_INTERFACE (TYPE_NAME (mclass)) | |
209 | ? CONSTANT_InterfaceMethodref | |
210 | : CONSTANT_Methodref, | |
377029eb | 211 | (class_index << 16) | name_type_index); |
212 | } | |
213 | ||
214 | #define PUT1(X) (*ptr++ = (X)) | |
215 | #define PUT2(X) (PUT1((X) >> 8), PUT1(X)) | |
216 | #define PUT4(X) (PUT2((X) >> 16), PUT2(X)) | |
443b1b77 | 217 | #define PUTN(P, N) (memcpy(ptr, (P), (N)), ptr += (N)) |
377029eb | 218 | |
219 | /* Give the number of bytes needed in a .class file for the CPOOL | |
220 | constant pool. Includes the 2-byte constant_pool_count. */ | |
221 | ||
222 | int | |
2883a3ed | 223 | count_constant_pool_bytes (CPool *cpool) |
377029eb | 224 | { |
225 | int size = 2; | |
226 | int i = 1; | |
533bc3bc | 227 | for ( ; i < cpool->count; i++) |
377029eb | 228 | { |
229 | size++; | |
230 | switch (cpool->tags[i]) | |
231 | { | |
232 | case CONSTANT_NameAndType: | |
233 | case CONSTANT_Fieldref: | |
234 | case CONSTANT_Methodref: | |
235 | case CONSTANT_InterfaceMethodref: | |
236 | case CONSTANT_Float: | |
237 | case CONSTANT_Integer: | |
238 | size += 4; | |
239 | break; | |
240 | case CONSTANT_Class: | |
241 | case CONSTANT_String: | |
242 | size += 2; | |
243 | break; | |
244 | case CONSTANT_Long: | |
245 | case CONSTANT_Double: | |
533bc3bc | 246 | size += 8; |
247 | i++; | |
377029eb | 248 | break; |
249 | case CONSTANT_Utf8: | |
250 | { | |
573aba85 | 251 | tree t = cpool->data[i].t; |
377029eb | 252 | int len = IDENTIFIER_LENGTH (t); |
253 | size += len + 2; | |
254 | } | |
255 | break; | |
533bc3bc | 256 | default: |
257 | /* Second word of CONSTANT_Long and CONSTANT_Double. */ | |
258 | size--; | |
377029eb | 259 | } |
260 | } | |
261 | return size; | |
262 | } | |
263 | ||
264 | /* Write the constant pool CPOOL into BUFFER. | |
265 | The length of BUFFER is LENGTH, which must match the needed length. */ | |
266 | ||
267 | void | |
2883a3ed | 268 | write_constant_pool (CPool *cpool, unsigned char *buffer, int length) |
377029eb | 269 | { |
f060a027 | 270 | unsigned char *ptr = buffer; |
377029eb | 271 | int i = 1; |
573aba85 | 272 | union cpool_entry *datap = &cpool->data[1]; |
377029eb | 273 | PUT2 (cpool->count); |
274 | for ( ; i < cpool->count; i++, datap++) | |
275 | { | |
276 | int tag = cpool->tags[i]; | |
277 | PUT1 (tag); | |
278 | switch (tag) | |
279 | { | |
280 | case CONSTANT_NameAndType: | |
281 | case CONSTANT_Fieldref: | |
282 | case CONSTANT_Methodref: | |
283 | case CONSTANT_InterfaceMethodref: | |
284 | case CONSTANT_Float: | |
285 | case CONSTANT_Integer: | |
573aba85 | 286 | PUT4 (datap->w); |
377029eb | 287 | break; |
288 | case CONSTANT_Class: | |
289 | case CONSTANT_String: | |
573aba85 | 290 | PUT2 (datap->w); |
377029eb | 291 | break; |
292 | break; | |
293 | case CONSTANT_Long: | |
294 | case CONSTANT_Double: | |
573aba85 | 295 | PUT4(datap->w); |
377029eb | 296 | i++; |
297 | datap++; | |
573aba85 | 298 | PUT4 (datap->w); |
377029eb | 299 | break; |
300 | case CONSTANT_Utf8: | |
301 | { | |
573aba85 | 302 | tree t = datap->t; |
377029eb | 303 | int len = IDENTIFIER_LENGTH (t); |
304 | PUT2 (len); | |
305 | PUTN (IDENTIFIER_POINTER (t), len); | |
306 | } | |
307 | break; | |
308 | } | |
309 | } | |
f060a027 | 310 | |
bc031ffe | 311 | gcc_assert (ptr == buffer + length); |
377029eb | 312 | } |
313 | ||
1f3233d1 | 314 | static GTY(()) tree tag_nodes[13]; |
003019ba | 315 | static tree |
2883a3ed | 316 | get_tag_node (int tag) |
377029eb | 317 | { |
7c446c95 | 318 | /* A Cache for build_int_cst (CONSTANT_XXX, 0). */ |
48c9f822 | 319 | |
65bf3316 | 320 | if (tag >= 13) |
321 | return build_int_cst (NULL_TREE, tag); | |
322 | ||
377029eb | 323 | if (tag_nodes[tag] == NULL_TREE) |
7016c612 | 324 | tag_nodes[tag] = build_int_cst (NULL_TREE, tag); |
377029eb | 325 | return tag_nodes[tag]; |
326 | } | |
327 | ||
ce1d036c | 328 | /* Given a class, return its constant pool, creating one if necessary. */ |
329 | ||
65bf3316 | 330 | CPool * |
ead29d98 | 331 | cpool_for_class (tree klass) |
ce1d036c | 332 | { |
ead29d98 | 333 | CPool *cpool = TYPE_CPOOL (klass); |
ce1d036c | 334 | |
335 | if (cpool == NULL) | |
336 | { | |
25a27413 | 337 | cpool = ggc_cleared_alloc<CPool> (); |
ead29d98 | 338 | TYPE_CPOOL (klass) = cpool; |
ce1d036c | 339 | } |
340 | return cpool; | |
341 | } | |
342 | ||
377029eb | 343 | /* Look for a constant pool entry that matches TAG and NAME. |
344 | Creates a new entry if not found. | |
345 | TAG is one of CONSTANT_Utf8, CONSTANT_String or CONSTANT_Class. | |
346 | NAME is an IDENTIFIER_NODE naming the Utf8 constant, string, or class. | |
347 | Returns the index of the entry. */ | |
348 | ||
349 | int | |
2883a3ed | 350 | alloc_name_constant (int tag, tree name) |
377029eb | 351 | { |
757f6c6c | 352 | CPool *outgoing_cpool = cpool_for_class (output_class); |
573aba85 | 353 | return find_tree_constant (outgoing_cpool, tag, name); |
377029eb | 354 | } |
355 | ||
f53ce661 | 356 | /* Create a constant pool entry for a name_and_type. This one has '.' |
357 | rather than '/' because it isn't going into a class file, it's | |
358 | going into a compiled object. We don't use the '/' separator in | |
359 | compiled objects. */ | |
360 | ||
361 | static int | |
362 | find_name_and_type_constant_tree (CPool *cpool, tree name, tree type) | |
363 | { | |
364 | int name_index = find_utf8_constant (cpool, name); | |
365 | int type_index | |
366 | = find_utf8_constant (cpool, | |
367 | identifier_subst (build_java_signature (type), | |
368 | "", '/', '.', "")); | |
369 | return find_constant1 (cpool, CONSTANT_NameAndType, | |
370 | (name_index << 16) | type_index); | |
371 | } | |
372 | ||
373 | /* Look for a field ref that matches DECL in the constant pool of | |
ead29d98 | 374 | KLASS. |
f53ce661 | 375 | Return the index of the entry. */ |
376 | ||
377 | int | |
ead29d98 | 378 | alloc_constant_fieldref (tree klass, tree decl) |
f53ce661 | 379 | { |
ead29d98 | 380 | CPool *outgoing_cpool = cpool_for_class (klass); |
f53ce661 | 381 | int class_index |
382 | = find_tree_constant (outgoing_cpool, CONSTANT_Class, | |
383 | DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl)))); | |
384 | int name_type_index | |
385 | = find_name_and_type_constant_tree (outgoing_cpool, DECL_NAME (decl), | |
386 | TREE_TYPE (decl)); | |
387 | return find_constant1 (outgoing_cpool, CONSTANT_Fieldref, | |
388 | (class_index << 16) | name_type_index); | |
389 | } | |
390 | ||
377029eb | 391 | /* Build an identifier for the internal name of reference type TYPE. */ |
392 | ||
393 | tree | |
2883a3ed | 394 | build_internal_class_name (tree type) |
377029eb | 395 | { |
396 | tree name; | |
397 | if (TYPE_ARRAY_P (type)) | |
398 | name = build_java_signature (type); | |
399 | else | |
400 | { | |
401 | name = TYPE_NAME (type); | |
402 | if (TREE_CODE (name) != IDENTIFIER_NODE) | |
403 | name = DECL_NAME (name); | |
404 | name = identifier_subst (name, "", '.', '/', ""); | |
405 | } | |
406 | return name; | |
407 | } | |
408 | ||
409 | /* Look for a CONSTANT_Class entry for CLAS, creating a new one if needed. */ | |
410 | ||
411 | int | |
2883a3ed | 412 | alloc_class_constant (tree clas) |
377029eb | 413 | { |
8f3ce25c | 414 | tree class_name = build_internal_class_name (clas); |
415 | ||
377029eb | 416 | return alloc_name_constant (CONSTANT_Class, |
8f3ce25c | 417 | (unmangle_classname |
418 | (IDENTIFIER_POINTER(class_name), | |
419 | IDENTIFIER_LENGTH(class_name)))); | |
377029eb | 420 | } |
421 | ||
4ee9c684 | 422 | /* Return the decl of the data array of the current constant pool. */ |
377029eb | 423 | |
cd725222 | 424 | tree |
425 | build_constant_data_ref (bool indirect) | |
377029eb | 426 | { |
cd725222 | 427 | if (indirect) |
428 | { | |
429 | tree d; | |
430 | tree cpool_type = build_array_type (ptr_type_node, NULL_TREE); | |
431 | tree decl = build_class_ref (output_class); | |
432 | tree klass = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (decl)), | |
433 | decl); | |
434 | tree constants = build3 (COMPONENT_REF, | |
435 | TREE_TYPE (constants_field_decl_node), klass, | |
436 | constants_field_decl_node, | |
437 | NULL_TREE); | |
438 | tree data = build3 (COMPONENT_REF, | |
439 | TREE_TYPE (constants_data_field_decl_node), | |
440 | constants, | |
441 | constants_data_field_decl_node, | |
442 | NULL_TREE); | |
deff3a7f | 443 | |
cd725222 | 444 | TREE_THIS_NOTRAP (klass) = 1; |
445 | data = fold_convert (build_pointer_type (cpool_type), data); | |
446 | d = build1 (INDIRECT_REF, cpool_type, data); | |
cd725222 | 447 | |
448 | return d; | |
449 | } | |
450 | else | |
377029eb | 451 | { |
757f6c6c | 452 | tree decl_name = mangled_classname ("_CD_", output_class); |
958a71b8 | 453 | tree decl = IDENTIFIER_GLOBAL_VALUE (decl_name); |
4ee9c684 | 454 | |
958a71b8 | 455 | if (! decl) |
456 | { | |
457 | /* Build a type with unspecified bounds. The will make sure | |
458 | that targets do the right thing with whatever size we end | |
459 | up with at the end. Using bounds that are too small risks | |
460 | assuming the data is in the small data section. */ | |
461 | tree type = build_array_type (ptr_type_node, NULL_TREE); | |
462 | ||
463 | /* We need to lay out the type ourselves, since build_array_type | |
464 | thinks the type is incomplete. */ | |
465 | layout_type (type); | |
466 | ||
e60a6f7b | 467 | decl = build_decl (input_location, VAR_DECL, decl_name, type); |
958a71b8 | 468 | TREE_STATIC (decl) = 1; |
469 | IDENTIFIER_GLOBAL_VALUE (decl_name) = decl; | |
470 | } | |
4ee9c684 | 471 | |
cd725222 | 472 | return decl; |
473 | } | |
377029eb | 474 | } |
475 | ||
476 | /* Get the pointer value at the INDEX'th element of the constant pool. */ | |
477 | ||
478 | tree | |
2883a3ed | 479 | build_ref_from_constant_pool (int index) |
377029eb | 480 | { |
cd725222 | 481 | tree i; |
482 | tree d = TYPE_CPOOL_DATA_REF (output_class); | |
483 | ||
484 | if (d == NULL_TREE) | |
485 | d = build_constant_data_ref (flag_indirect_classes); | |
486 | ||
487 | i = build_int_cst (NULL_TREE, index); | |
2934c6b5 | 488 | d = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i, |
e3f81426 | 489 | NULL_TREE, NULL_TREE); |
2934c6b5 | 490 | return d; |
377029eb | 491 | } |
492 | ||
4f9026a9 | 493 | /* Build an initializer for the constants field of the current constant pool. |
377029eb | 494 | Should only be called at top-level, since it may emit declarations. */ |
495 | ||
496 | tree | |
2883a3ed | 497 | build_constants_constructor (void) |
377029eb | 498 | { |
ce1d036c | 499 | CPool *outgoing_cpool = cpool_for_class (current_class); |
377029eb | 500 | tree tags_value, data_value; |
501 | tree cons; | |
f1f41a6c | 502 | vec<constructor_elt, va_gc> *v = NULL; |
377029eb | 503 | int i; |
f1f41a6c | 504 | vec<constructor_elt, va_gc> *tags = NULL; |
505 | vec<constructor_elt, va_gc> *data = NULL; | |
2a488311 | 506 | constructor_elt *t = NULL; |
507 | constructor_elt *d = NULL; | |
65bf3316 | 508 | |
2a488311 | 509 | if (outgoing_cpool->count > 0) |
510 | { | |
511 | int c = outgoing_cpool->count; | |
f1f41a6c | 512 | vec_safe_grow_cleared (tags, c); |
513 | vec_safe_grow_cleared (data, c); | |
514 | t = &(*tags)[c-1]; | |
515 | d = &(*data)[c-1]; | |
2a488311 | 516 | } |
517 | ||
518 | #define CONSTRUCTOR_PREPEND_VALUE(E, V) E->value = V, E-- | |
377029eb | 519 | for (i = outgoing_cpool->count; --i > 0; ) |
65bf3316 | 520 | switch (outgoing_cpool->tags[i] & ~CONSTANT_LazyFlag) |
f53ce661 | 521 | { |
65bf3316 | 522 | case CONSTANT_None: /* The second half of a Double or Long on a |
523 | 32-bit target. */ | |
f53ce661 | 524 | case CONSTANT_Fieldref: |
525 | case CONSTANT_NameAndType: | |
65bf3316 | 526 | case CONSTANT_Float: |
527 | case CONSTANT_Integer: | |
528 | case CONSTANT_Double: | |
529 | case CONSTANT_Long: | |
530 | case CONSTANT_Methodref: | |
531 | case CONSTANT_InterfaceMethodref: | |
f53ce661 | 532 | { |
ae272bde | 533 | unsigned HOST_WIDE_INT temp = outgoing_cpool->data[i].w; |
534 | ||
7cff3d6b | 535 | /* Make sure that on a big-endian machine with 64-bit |
536 | pointers this 32-bit jint appears in the first word. | |
ae272bde | 537 | FIXME: This is a kludge. The field we're initializing is |
538 | not a scalar but a union, and that's how we should | |
539 | represent it in the compiler. We should fix this. */ | |
fe08dd82 | 540 | if (BYTES_BIG_ENDIAN) |
541 | temp <<= ((POINTER_SIZE > 32) ? POINTER_SIZE - 32 : 0); | |
f53ce661 | 542 | |
2a488311 | 543 | CONSTRUCTOR_PREPEND_VALUE (t, get_tag_node (outgoing_cpool->tags[i])); |
c00e363f | 544 | CONSTRUCTOR_PREPEND_VALUE (d, build_int_cst (ptr_type_node, temp)); |
f53ce661 | 545 | } |
546 | break; | |
65bf3316 | 547 | |
548 | case CONSTANT_Class: | |
549 | case CONSTANT_String: | |
550 | case CONSTANT_Unicode: | |
551 | case CONSTANT_Utf8: | |
2a488311 | 552 | CONSTRUCTOR_PREPEND_VALUE (t, get_tag_node (outgoing_cpool->tags[i])); |
553 | CONSTRUCTOR_PREPEND_VALUE (d, build_utf8_ref (outgoing_cpool->data[i].t)); | |
f53ce661 | 554 | break; |
65bf3316 | 555 | |
556 | default: | |
557 | gcc_assert (false); | |
f53ce661 | 558 | } |
2a488311 | 559 | #undef CONSTRUCTOR_PREPEND_VALUE |
560 | ||
377029eb | 561 | if (outgoing_cpool->count > 0) |
562 | { | |
377029eb | 563 | tree data_decl, tags_decl, tags_type; |
7016c612 | 564 | tree max_index = build_int_cst (sizetype, outgoing_cpool->count - 1); |
7c446c95 | 565 | tree index_type = build_index_type (max_index); |
ae2a9b00 | 566 | tree tem; |
377029eb | 567 | |
568 | /* Add dummy 0'th element of constant pool. */ | |
f1f41a6c | 569 | gcc_assert (t == tags->address ()); |
570 | gcc_assert (d == data->address ()); | |
2a488311 | 571 | t->value = get_tag_node (0); |
572 | d->value = null_pointer_node; | |
377029eb | 573 | |
ae2a9b00 | 574 | /* Change the type of the decl to have the proper array size. |
575 | ??? Make sure to transition the old type-pointer-to list to this | |
576 | new type to not invalidate all build address expressions. */ | |
cd725222 | 577 | data_decl = build_constant_data_ref (false); |
ae2a9b00 | 578 | tem = TYPE_POINTER_TO (TREE_TYPE (data_decl)); |
579 | if (!tem) | |
580 | tem = build_pointer_type (TREE_TYPE (data_decl)); | |
581 | TYPE_POINTER_TO (TREE_TYPE (data_decl)) = NULL_TREE; | |
f53ce661 | 582 | TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type); |
ae2a9b00 | 583 | TYPE_POINTER_TO (TREE_TYPE (data_decl)) = tem; |
2a488311 | 584 | DECL_INITIAL (data_decl) = build_constructor (TREE_TYPE (data_decl), data); |
377029eb | 585 | DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl)); |
b278476e | 586 | DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl)); |
b2c4af5e | 587 | rest_of_decl_compilation (data_decl, 1, 0); |
377029eb | 588 | data_value = build_address_of (data_decl); |
589 | ||
590 | tags_type = build_array_type (unsigned_byte_type_node, index_type); | |
e60a6f7b | 591 | tags_decl = build_decl (input_location, |
592 | VAR_DECL, mangled_classname ("_CT_", | |
377029eb | 593 | current_class), |
594 | tags_type); | |
595 | TREE_STATIC (tags_decl) = 1; | |
2a488311 | 596 | DECL_INITIAL (tags_decl) = build_constructor (tags_type, tags); |
b2c4af5e | 597 | rest_of_decl_compilation (tags_decl, 1, 0); |
377029eb | 598 | tags_value = build_address_of (tags_decl); |
599 | } | |
600 | else | |
601 | { | |
602 | data_value = null_pointer_node; | |
603 | tags_value = null_pointer_node; | |
604 | } | |
3eafef1a | 605 | START_RECORD_CONSTRUCTOR (v, constants_type_node); |
606 | PUSH_FIELD_VALUE (v, "size", | |
7016c612 | 607 | build_int_cst (NULL_TREE, outgoing_cpool->count)); |
3eafef1a | 608 | PUSH_FIELD_VALUE (v, "tags", tags_value); |
609 | PUSH_FIELD_VALUE (v, "data", data_value); | |
610 | FINISH_RECORD_CONSTRUCTOR (cons, v, constants_type_node); | |
377029eb | 611 | return cons; |
612 | } | |
1f3233d1 | 613 | |
614 | #include "gt-java-constants.h" |