]>
Commit | Line | Data |
---|---|---|
e04a16fb | 1 | /* Functions related to building classes and their related objects. |
97b8365c | 2 | Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, |
2d593c86 | 3 | 2005, 2006, 2007, 2008 Free Software Foundation, Inc. |
e04a16fb | 4 | |
f309ff0a | 5 | This file is part of GCC. |
e04a16fb | 6 | |
f309ff0a | 7 | GCC is free software; you can redistribute it and/or modify |
e04a16fb | 8 | it under the terms of the GNU General Public License as published by |
8328d52a | 9 | the Free Software Foundation; either version 3, or (at your option) |
e04a16fb AG |
10 | any later version. |
11 | ||
f309ff0a | 12 | GCC is distributed in the hope that it will be useful, |
e04a16fb AG |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
8328d52a NC |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. | |
e04a16fb AG |
20 | |
21 | Java and all Java-based marks are trademarks or registered trademarks | |
22 | of Sun Microsystems, Inc. in the United States and other countries. | |
23 | The Free Software Foundation is independent of Sun Microsystems, Inc. */ | |
24 | ||
25 | /* Written by Per Bothner <bothner@cygnus.com> */ | |
26 | ||
e04a16fb | 27 | #include "config.h" |
1f43f4b4 | 28 | #include "system.h" |
4977bab6 ZW |
29 | #include "coretypes.h" |
30 | #include "tm.h" | |
e04a16fb AG |
31 | #include "tree.h" |
32 | #include "rtl.h" | |
75d01ad7 | 33 | #include "flags.h" |
e04a16fb AG |
34 | #include "java-tree.h" |
35 | #include "jcf.h" | |
36 | #include "obstack.h" | |
1f43f4b4 | 37 | #include "toplev.h" |
d4476be2 KG |
38 | #include "output.h" |
39 | #include "parse.h" | |
2cc07db4 | 40 | #include "function.h" |
19e223db | 41 | #include "ggc.h" |
7be5b0e5 | 42 | #include "stdio.h" |
6351543d | 43 | #include "target.h" |
85194ee9 | 44 | #include "except.h" |
36739040 | 45 | #include "cgraph.h" |
c9b9aa64 | 46 | #include "tree-iterator.h" |
cd9c7bd2 | 47 | #include "cgraph.h" |
97b8365c | 48 | #include "vecprim.h" |
e04a16fb | 49 | |
7be5b0e5 AG |
50 | /* DOS brain-damage */ |
51 | #ifndef O_BINARY | |
52 | #define O_BINARY 0 /* MS-DOS brain-damage */ | |
53 | #endif | |
54 | ||
d2097937 KG |
55 | static tree make_method_value (tree); |
56 | static tree build_java_method_type (tree, tree, int); | |
57 | static int32 hashUtf8String (const char *, int); | |
58 | static tree make_field_value (tree); | |
59 | static tree get_dispatch_vector (tree); | |
60 | static tree get_dispatch_table (tree, tree); | |
5c64ead4 | 61 | static int supers_all_compiled (tree type); |
d2097937 | 62 | static tree maybe_layout_super_class (tree, tree); |
aecf4109 | 63 | static void add_miranda_methods (tree, tree); |
d2097937 | 64 | static int assume_compiled (const char *); |
313ab5ee | 65 | static tree build_symbol_entry (tree, tree); |
36739040 | 66 | static tree emit_assertion_table (tree); |
8cfb12bf | 67 | static void register_class (void); |
861ef928 | 68 | |
1f8f4a0b | 69 | struct obstack temporary_obstack; |
e04a16fb | 70 | |
97b8365c TT |
71 | static const char *cyclic_inheritance_report; |
72 | ||
48aedbca AG |
73 | /* The compiler generates different code depending on whether or not |
74 | it can assume certain classes have been compiled down to native | |
75 | code or not. The compiler options -fassume-compiled= and | |
76 | -fno-assume-compiled= are used to create a tree of | |
24d82bce | 77 | class_flag_node objects. This tree is queried to determine if |
48aedbca AG |
78 | a class is assume to be compiled or not. Each node in the tree |
79 | represents either a package or a specific class. */ | |
80 | ||
24d82bce | 81 | typedef struct class_flag_node_struct |
48aedbca AG |
82 | { |
83 | /* The class or package name. */ | |
84 | const char *ident; | |
85 | ||
ee142fe7 | 86 | /* Nonzero if this represents an exclusion. */ |
24d82bce | 87 | int value; |
48aedbca AG |
88 | |
89 | /* Pointers to other nodes in the tree. */ | |
24d82bce PB |
90 | struct class_flag_node_struct *parent; |
91 | struct class_flag_node_struct *sibling; | |
92 | struct class_flag_node_struct *child; | |
93 | } class_flag_node; | |
48aedbca | 94 | |
24d82bce PB |
95 | static class_flag_node *find_class_flag_node (class_flag_node *, const char *); |
96 | static void add_class_flag (class_flag_node **, const char *, int); | |
c63b98cd | 97 | |
48aedbca AG |
98 | /* This is the root of the include/exclude tree. */ |
99 | ||
24d82bce PB |
100 | static class_flag_node *assume_compiled_tree; |
101 | ||
102 | static class_flag_node *enable_assert_tree; | |
48aedbca | 103 | |
8cfb12bf RH |
104 | static GTY(()) tree class_roots[4]; |
105 | #define fields_ident class_roots[0] /* get_identifier ("fields") */ | |
106 | #define info_ident class_roots[1] /* get_identifier ("info") */ | |
107 | #define class_list class_roots[2] | |
108 | #define class_dtable_decl class_roots[3] | |
109 | ||
110 | static GTY(()) VEC(tree,gc) *registered_class; | |
b5c4fed9 | 111 | |
b4e18eee AH |
112 | /* A tree that returns the address of the class$ of the class |
113 | currently being compiled. */ | |
114 | static GTY(()) tree this_classdollar; | |
115 | ||
48aedbca | 116 | /* Return the node that most closely represents the class whose name |
24d82bce PB |
117 | is IDENT. Start the search from NODE (followed by its siblings). |
118 | Return NULL if an appropriate node does not exist. */ | |
48aedbca | 119 | |
24d82bce PB |
120 | static class_flag_node * |
121 | find_class_flag_node (class_flag_node *node, const char *ident) | |
48aedbca AG |
122 | { |
123 | while (node) | |
124 | { | |
125 | size_t node_ident_length = strlen (node->ident); | |
126 | ||
127 | /* node_ident_length is zero at the root of the tree. If the | |
128 | identifiers are the same length, then we have matching | |
129 | classes. Otherwise check if we've matched an enclosing | |
130 | package name. */ | |
131 | ||
132 | if (node_ident_length == 0 | |
133 | || (strncmp (ident, node->ident, node_ident_length) == 0 | |
24d82bce | 134 | && (ident[node_ident_length] == '\0' |
48aedbca AG |
135 | || ident[node_ident_length] == '.'))) |
136 | { | |
137 | /* We've found a match, however, there might be a more | |
138 | specific match. */ | |
139 | ||
24d82bce | 140 | class_flag_node *found = find_class_flag_node (node->child, ident); |
48aedbca AG |
141 | if (found) |
142 | return found; | |
143 | else | |
144 | return node; | |
145 | } | |
146 | ||
147 | /* No match yet. Continue through the sibling list. */ | |
148 | node = node->sibling; | |
149 | } | |
150 | ||
151 | /* No match at all in this tree. */ | |
152 | return NULL; | |
153 | } | |
154 | ||
48aedbca | 155 | void |
24d82bce | 156 | add_class_flag (class_flag_node **rootp, const char *ident, int value) |
48aedbca | 157 | { |
24d82bce PB |
158 | class_flag_node *root = *rootp; |
159 | class_flag_node *parent, *node; | |
48aedbca AG |
160 | |
161 | /* Create the root of the tree if it doesn't exist yet. */ | |
162 | ||
24d82bce | 163 | if (NULL == root) |
48aedbca | 164 | { |
5ed6ace5 | 165 | root = XNEW (class_flag_node); |
24d82bce PB |
166 | root->ident = ""; |
167 | root->value = 0; | |
168 | root->sibling = NULL; | |
169 | root->child = NULL; | |
170 | root->parent = NULL; | |
171 | *rootp = root; | |
48aedbca AG |
172 | } |
173 | ||
174 | /* Calling the function with the empty string means we're setting | |
24d82bce | 175 | value for the root of the hierarchy. */ |
48aedbca AG |
176 | |
177 | if (0 == ident[0]) | |
178 | { | |
24d82bce | 179 | root->value = value; |
48aedbca AG |
180 | return; |
181 | } | |
182 | ||
183 | /* Find the parent node for this new node. PARENT will either be a | |
184 | class or a package name. Adjust PARENT accordingly. */ | |
185 | ||
24d82bce PB |
186 | parent = find_class_flag_node (root, ident); |
187 | if (strcmp (ident, parent->ident) == 0) | |
188 | parent->value = value; | |
189 | else | |
190 | { | |
191 | /* Insert new node into the tree. */ | |
5ed6ace5 | 192 | node = XNEW (class_flag_node); |
24d82bce PB |
193 | |
194 | node->ident = xstrdup (ident); | |
195 | node->value = value; | |
196 | node->child = NULL; | |
197 | ||
198 | node->parent = parent; | |
199 | node->sibling = parent->child; | |
200 | parent->child = node; | |
201 | } | |
202 | } | |
203 | ||
204 | /* Add a new IDENT to the include/exclude tree. It's an exclusion | |
205 | if EXCLUDEP is nonzero. */ | |
206 | ||
207 | void | |
208 | add_assume_compiled (const char *ident, int excludep) | |
209 | { | |
210 | add_class_flag (&assume_compiled_tree, ident, excludep); | |
211 | } | |
48aedbca | 212 | |
c048d56d | 213 | /* The default value returned by enable_assertions. */ |
48aedbca | 214 | |
6e63e240 | 215 | #define DEFAULT_ENABLE_ASSERT (optimize == 0) |
24d82bce PB |
216 | |
217 | /* Enter IDENT (a class or package name) into the enable-assertions table. | |
218 | VALUE is true to enable and false to disable. */ | |
219 | ||
220 | void | |
221 | add_enable_assert (const char *ident, int value) | |
222 | { | |
223 | if (enable_assert_tree == NULL) | |
224 | add_class_flag (&enable_assert_tree, "", DEFAULT_ENABLE_ASSERT); | |
225 | add_class_flag (&enable_assert_tree, ident, value); | |
48aedbca AG |
226 | } |
227 | ||
ee142fe7 | 228 | /* Returns nonzero if IDENT is the name of a class that the compiler |
b47ffb8f | 229 | should assume has been compiled to object code. */ |
48aedbca | 230 | |
c63b98cd | 231 | static int |
0a2f0c54 | 232 | assume_compiled (const char *ident) |
48aedbca | 233 | { |
24d82bce | 234 | class_flag_node *i; |
48aedbca AG |
235 | int result; |
236 | ||
237 | if (NULL == assume_compiled_tree) | |
238 | return 1; | |
239 | ||
24d82bce | 240 | i = find_class_flag_node (assume_compiled_tree, ident); |
48aedbca | 241 | |
24d82bce | 242 | result = ! i->value; |
48aedbca AG |
243 | |
244 | return (result); | |
245 | } | |
246 | ||
24d82bce PB |
247 | /* Return true if we should generate code to check assertions within KLASS. */ |
248 | ||
249 | bool | |
250 | enable_assertions (tree klass) | |
251 | { | |
c048d56d | 252 | /* Check if command-line specifies whether we should check assertions. */ |
24d82bce PB |
253 | |
254 | if (klass != NULL_TREE && DECL_NAME (klass) && enable_assert_tree != NULL) | |
255 | { | |
256 | const char *ident = IDENTIFIER_POINTER (DECL_NAME (klass)); | |
257 | class_flag_node *node | |
258 | = find_class_flag_node (enable_assert_tree, ident); | |
259 | return node->value; | |
260 | } | |
261 | ||
262 | /* The default is to enable assertions if generating class files, | |
263 | or not optimizing. */ | |
264 | return DEFAULT_ENABLE_ASSERT; | |
265 | } | |
266 | ||
e04a16fb AG |
267 | /* Return an IDENTIFIER_NODE the same as (OLD_NAME, OLD_LENGTH). |
268 | except that characters matching OLD_CHAR are substituted by NEW_CHAR. | |
269 | Also, PREFIX is prepended, and SUFFIX is appended. */ | |
270 | ||
271 | tree | |
0a2f0c54 KG |
272 | ident_subst (const char* old_name, |
273 | int old_length, | |
274 | const char *prefix, | |
275 | int old_char, | |
276 | int new_char, | |
277 | const char *suffix) | |
e04a16fb AG |
278 | { |
279 | int prefix_len = strlen (prefix); | |
280 | int suffix_len = strlen (suffix); | |
281 | int i = prefix_len + old_length + suffix_len + 1; | |
a92cb0c3 | 282 | char *buffer = alloca (i); |
7cefa0c1 | 283 | |
e04a16fb AG |
284 | strcpy (buffer, prefix); |
285 | for (i = 0; i < old_length; i++) | |
286 | { | |
287 | char ch = old_name[i]; | |
288 | if (ch == old_char) | |
289 | ch = new_char; | |
290 | buffer[prefix_len + i] = ch; | |
291 | } | |
292 | strcpy (buffer + prefix_len + old_length, suffix); | |
293 | return get_identifier (buffer); | |
294 | } | |
295 | ||
296 | /* Return an IDENTIFIER_NODE the same as OLD_ID, | |
297 | except that characters matching OLD_CHAR are substituted by NEW_CHAR. | |
298 | Also, PREFIX is prepended, and SUFFIX is appended. */ | |
299 | ||
300 | tree | |
0a2f0c54 KG |
301 | identifier_subst (const tree old_id, |
302 | const char *prefix, | |
303 | int old_char, | |
304 | int new_char, | |
305 | const char *suffix) | |
e04a16fb AG |
306 | { |
307 | return ident_subst (IDENTIFIER_POINTER (old_id), IDENTIFIER_LENGTH (old_id), | |
308 | prefix, old_char, new_char, suffix); | |
309 | } | |
310 | ||
311 | /* Generate a valid C identifier from the name of the class TYPE, | |
312 | prefixed by PREFIX. */ | |
313 | ||
314 | tree | |
0a2f0c54 | 315 | mangled_classname (const char *prefix, tree type) |
e04a16fb | 316 | { |
6d2c26de | 317 | tree result; |
e04a16fb AG |
318 | tree ident = TYPE_NAME (type); |
319 | if (TREE_CODE (ident) != IDENTIFIER_NODE) | |
320 | ident = DECL_NAME (ident); | |
6d2c26de AH |
321 | result = identifier_subst (ident, prefix, '.', '_', ""); |
322 | ||
323 | /* Replace any characters that aren't in the set [0-9a-zA-Z_$] with | |
324 | "_0xXX". Class names containing such chracters are uncommon, but | |
325 | they do sometimes occur in class files. Without this check, | |
326 | these names cause assembly errors. | |
327 | ||
328 | There is a possibility that a real class name could conflict with | |
329 | the identifier we generate, but it is unlikely and will | |
330 | immediately be detected as an assembler error. At some point we | |
331 | should do something more elaborate (perhaps using the full | |
332 | unicode mangling scheme) in order to prevent such a conflict. */ | |
333 | { | |
334 | int i; | |
335 | const int len = IDENTIFIER_LENGTH (result); | |
336 | const char *p = IDENTIFIER_POINTER (result); | |
337 | int illegal_chars = 0; | |
338 | ||
339 | /* Make two passes over the identifier. The first pass is merely | |
340 | to count illegal characters; we need to do this in order to | |
341 | allocate a buffer. */ | |
342 | for (i = 0; i < len; i++) | |
343 | { | |
344 | char c = p[i]; | |
345 | illegal_chars += (! ISALNUM (c) && c != '_' && c != '$'); | |
346 | } | |
347 | ||
348 | /* And the second pass, which is rarely executed, does the | |
349 | rewriting. */ | |
350 | if (illegal_chars != 0) | |
351 | { | |
352 | char *buffer = alloca (illegal_chars * 4 + len + 1); | |
353 | int j; | |
354 | ||
355 | for (i = 0, j = 0; i < len; i++) | |
356 | { | |
357 | char c = p[i]; | |
358 | if (! ISALNUM (c) && c != '_' && c != '$') | |
359 | { | |
360 | buffer[j++] = '_'; | |
361 | sprintf (&buffer[j], "0x%02x", c); | |
362 | j += 4; | |
363 | } | |
364 | else | |
365 | buffer[j++] = c; | |
366 | } | |
367 | ||
368 | buffer[j] = 0; | |
369 | result = get_identifier (buffer); | |
370 | } | |
371 | } | |
372 | ||
373 | return result; | |
e04a16fb AG |
374 | } |
375 | ||
376 | tree | |
0a2f0c54 | 377 | make_class (void) |
e04a16fb AG |
378 | { |
379 | tree type; | |
e04a16fb | 380 | type = make_node (RECORD_TYPE); |
a93770ef NS |
381 | /* Unfortunately we must create the binfo here, so that class |
382 | loading works. */ | |
383 | TYPE_BINFO (type) = make_tree_binfo (0); | |
c2952b01 | 384 | MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type); |
e04a16fb AG |
385 | |
386 | return type; | |
387 | } | |
388 | ||
389 | /* Given a fully-qualified classname in NAME (whose length is NAME_LENGTH), | |
390 | and where each of the constituents is separated by '/', | |
391 | return a corresponding IDENTIFIER_NODE, except using '.' as separator. */ | |
392 | ||
393 | tree | |
0a2f0c54 | 394 | unmangle_classname (const char *name, int name_length) |
e04a16fb | 395 | { |
c877974e | 396 | tree to_return = ident_subst (name, name_length, "", '/', '.', ""); |
1982388a APB |
397 | /* It's not sufficient to compare to_return and get_identifier |
398 | (name) to determine whether to_return is qualified. There are | |
399 | cases in signature analysis where name will be stripped of a | |
400 | trailing ';'. */ | |
401 | name = IDENTIFIER_POINTER (to_return); | |
402 | while (*name) | |
403 | if (*name++ == '.') | |
404 | { | |
405 | QUALIFIED_P (to_return) = 1; | |
406 | break; | |
407 | } | |
408 | ||
c877974e | 409 | return to_return; |
e04a16fb AG |
410 | } |
411 | ||
36739040 TT |
412 | #define GEN_TABLE(TABLE, NAME, TABLE_TYPE, TYPE) \ |
413 | do \ | |
414 | { \ | |
415 | const char *typename = IDENTIFIER_POINTER (mangled_classname ("", TYPE)); \ | |
416 | char *buf = alloca (strlen (typename) + strlen (#NAME "_syms_") + 1); \ | |
417 | tree decl; \ | |
418 | \ | |
419 | sprintf (buf, #NAME "_%s", typename); \ | |
420 | TYPE_## TABLE ##_DECL (type) = decl = \ | |
421 | build_decl (VAR_DECL, get_identifier (buf), TABLE_TYPE); \ | |
422 | DECL_EXTERNAL (decl) = 1; \ | |
423 | TREE_STATIC (decl) = 1; \ | |
424 | TREE_READONLY (decl) = 1; \ | |
425 | TREE_CONSTANT (decl) = 1; \ | |
426 | DECL_IGNORED_P (decl) = 1; \ | |
427 | /* Mark the table as belonging to this class. */ \ | |
428 | pushdecl (decl); \ | |
429 | MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); \ | |
430 | DECL_OWNER (decl) = TYPE; \ | |
431 | sprintf (buf, #NAME "_syms_%s", typename); \ | |
432 | TYPE_## TABLE ##_SYMS_DECL (TYPE) = \ | |
433 | build_decl (VAR_DECL, get_identifier (buf), symbols_array_type); \ | |
434 | TREE_STATIC (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1; \ | |
435 | TREE_CONSTANT (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1; \ | |
436 | DECL_IGNORED_P (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1; \ | |
36739040 TT |
437 | } \ |
438 | while (0) | |
85194ee9 | 439 | |
fe0b9fb5 RM |
440 | /* Given a class, create the DECLs for all its associated indirect |
441 | dispatch tables. */ | |
85194ee9 AH |
442 | void |
443 | gen_indirect_dispatch_tables (tree type) | |
444 | { | |
6d2c26de | 445 | const char *typename = IDENTIFIER_POINTER (mangled_classname ("", type)); |
85194ee9 AH |
446 | { |
447 | tree field = NULL; | |
71e68384 | 448 | char *buf = alloca (strlen (typename) + strlen ("_catch_classes_") + 1); |
85194ee9 AH |
449 | tree catch_class_type = make_node (RECORD_TYPE); |
450 | ||
451 | sprintf (buf, "_catch_classes_%s", typename); | |
452 | PUSH_FIELD (catch_class_type, field, "address", utf8const_ptr_type); | |
453 | PUSH_FIELD (catch_class_type, field, "classname", ptr_type_node); | |
454 | FINISH_RECORD (catch_class_type); | |
455 | ||
456 | TYPE_CTABLE_DECL (type) | |
457 | = build_decl (VAR_DECL, get_identifier (buf), | |
458 | build_array_type (catch_class_type, 0)); | |
459 | DECL_EXTERNAL (TYPE_CTABLE_DECL (type)) = 1; | |
460 | TREE_STATIC (TYPE_CTABLE_DECL (type)) = 1; | |
461 | TREE_READONLY (TYPE_CTABLE_DECL (type)) = 1; | |
462 | TREE_CONSTANT (TYPE_CTABLE_DECL (type)) = 1; | |
463 | DECL_IGNORED_P (TYPE_CTABLE_DECL (type)) = 1; | |
464 | pushdecl (TYPE_CTABLE_DECL (type)); | |
465 | } | |
466 | ||
467 | if (flag_indirect_dispatch) | |
468 | { | |
36739040 TT |
469 | GEN_TABLE (ATABLE, _atable, atable_type, type); |
470 | GEN_TABLE (OTABLE, _otable, otable_type, type); | |
471 | GEN_TABLE (ITABLE, _itable, itable_type, type); | |
85194ee9 AH |
472 | } |
473 | } | |
474 | ||
36739040 TT |
475 | #undef GEN_TABLE |
476 | ||
e04a16fb | 477 | tree |
0a2f0c54 | 478 | push_class (tree class_type, tree class_name) |
e04a16fb AG |
479 | { |
480 | tree decl, signature; | |
1f9cc6db | 481 | location_t saved_loc = input_location; |
6744f400 | 482 | CLASS_P (class_type) = 1; |
e04a16fb | 483 | decl = build_decl (TYPE_DECL, class_name, class_type); |
e87047c6 | 484 | TYPE_DECL_SUPPRESS_DEBUG (decl) = 1; |
9d7d8362 APB |
485 | |
486 | /* dbxout needs a DECL_SIZE if in gstabs mode */ | |
487 | DECL_SIZE (decl) = integer_zero_node; | |
488 | ||
1f9cc6db | 489 | input_location = saved_loc; |
e04a16fb | 490 | signature = identifier_subst (class_name, "L", '.', '/', ";"); |
a7303141 | 491 | IDENTIFIER_SIGNATURE_TYPE (signature) = build_pointer_type (class_type); |
e04a16fb | 492 | |
a83f01f0 | 493 | /* Setting DECL_ARTIFICIAL forces dbxout.c to specific the type is |
e04a16fb AG |
494 | both a typedef and in the struct name-space. We may want to re-visit |
495 | this later, but for now it reduces the changes needed for gdb. */ | |
496 | DECL_ARTIFICIAL (decl) = 1; | |
497 | ||
498 | pushdecl_top_level (decl); | |
e04a16fb | 499 | |
e04a16fb AG |
500 | return decl; |
501 | } | |
502 | ||
503 | /* Finds the (global) class named NAME. Creates the class if not found. | |
504 | Also creates associated TYPE_DECL. | |
505 | Does not check if the class actually exists, load the class, | |
506 | fill in field or methods, or do layout_type. */ | |
507 | ||
508 | tree | |
0a2f0c54 | 509 | lookup_class (tree name) |
e04a16fb AG |
510 | { |
511 | tree decl = IDENTIFIER_CLASS_VALUE (name); | |
512 | if (decl == NULL_TREE) | |
513 | decl = push_class (make_class (), name); | |
514 | return TREE_TYPE (decl); | |
515 | } | |
516 | ||
517 | void | |
0a2f0c54 KG |
518 | set_super_info (int access_flags, tree this_class, |
519 | tree super_class, int interfaces_count) | |
e04a16fb AG |
520 | { |
521 | int total_supers = interfaces_count; | |
522 | tree class_decl = TYPE_NAME (this_class); | |
85fd2947 | 523 | |
e04a16fb AG |
524 | if (super_class) |
525 | total_supers++; | |
526 | ||
a93770ef NS |
527 | if (total_supers) |
528 | TYPE_BINFO (this_class) = make_tree_binfo (total_supers); | |
af434fa7 | 529 | TYPE_VFIELD (this_class) = TYPE_VFIELD (object_type_node); |
e04a16fb AG |
530 | if (super_class) |
531 | { | |
95b4aca6 | 532 | tree super_binfo = make_tree_binfo (0); |
e04a16fb AG |
533 | BINFO_TYPE (super_binfo) = super_class; |
534 | BINFO_OFFSET (super_binfo) = integer_zero_node; | |
fa743e8c | 535 | BINFO_BASE_APPEND (TYPE_BINFO (this_class), super_binfo); |
85fd2947 | 536 | CLASS_HAS_SUPER_FLAG (TYPE_BINFO (this_class)) = 1; |
e04a16fb | 537 | } |
3ff9925c | 538 | |
4a70e37e APB |
539 | set_class_decl_access_flags (access_flags, class_decl); |
540 | } | |
541 | ||
542 | void | |
0a2f0c54 | 543 | set_class_decl_access_flags (int access_flags, tree class_decl) |
4a70e37e | 544 | { |
e04a16fb AG |
545 | if (access_flags & ACC_PUBLIC) CLASS_PUBLIC (class_decl) = 1; |
546 | if (access_flags & ACC_FINAL) CLASS_FINAL (class_decl) = 1; | |
547 | if (access_flags & ACC_SUPER) CLASS_SUPER (class_decl) = 1; | |
548 | if (access_flags & ACC_INTERFACE) CLASS_INTERFACE (class_decl) = 1; | |
549 | if (access_flags & ACC_ABSTRACT) CLASS_ABSTRACT (class_decl) = 1; | |
c2952b01 | 550 | if (access_flags & ACC_STATIC) CLASS_STATIC (class_decl) = 1; |
cf1748bf | 551 | if (access_flags & ACC_PRIVATE) CLASS_PRIVATE (class_decl) = 1; |
4dbf4496 | 552 | if (access_flags & ACC_PROTECTED) CLASS_PROTECTED (class_decl) = 1; |
6b6294f1 | 553 | if (access_flags & ACC_STRICT) CLASS_STRICTFP (class_decl) = 1; |
97b8365c TT |
554 | if (access_flags & ACC_ENUM) CLASS_ENUM (class_decl) = 1; |
555 | if (access_flags & ACC_SYNTHETIC) CLASS_SYNTHETIC (class_decl) = 1; | |
556 | if (access_flags & ACC_ANNOTATION) CLASS_ANNOTATION (class_decl) = 1; | |
e04a16fb AG |
557 | } |
558 | ||
559 | /* Return length of inheritance chain of CLAS, where java.lang.Object is 0, | |
560 | direct sub-classes of Object are 1, and so on. */ | |
561 | ||
562 | int | |
0a2f0c54 | 563 | class_depth (tree clas) |
e04a16fb AG |
564 | { |
565 | int depth = 0; | |
566 | if (! CLASS_LOADED_P (clas)) | |
567 | load_class (clas, 1); | |
e920ebc9 APB |
568 | if (TYPE_SIZE (clas) == error_mark_node) |
569 | return -1; | |
e04a16fb AG |
570 | while (clas != object_type_node) |
571 | { | |
572 | depth++; | |
604a3205 | 573 | clas = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (clas), 0)); |
e04a16fb AG |
574 | } |
575 | return depth; | |
576 | } | |
577 | ||
578 | /* Return true iff TYPE2 is an interface that extends interface TYPE1 */ | |
579 | ||
580 | int | |
0a2f0c54 | 581 | interface_of_p (tree type1, tree type2) |
e04a16fb | 582 | { |
fa743e8c NS |
583 | int i; |
584 | tree binfo, base_binfo; | |
e04a16fb | 585 | |
968d62b5 | 586 | if (! TYPE_BINFO (type2)) |
e04a16fb | 587 | return 0; |
fa743e8c NS |
588 | |
589 | for (binfo = TYPE_BINFO (type2), i = 0; | |
590 | BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) | |
591 | if (BINFO_TYPE (base_binfo) == type1) | |
592 | return 1; | |
593 | ||
594 | for (binfo = TYPE_BINFO (type2), i = 0; | |
595 | BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) /* */ | |
596 | if (BINFO_TYPE (base_binfo) | |
597 | && interface_of_p (type1, BINFO_TYPE (base_binfo))) | |
598 | return 1; | |
599 | ||
e04a16fb AG |
600 | return 0; |
601 | } | |
602 | ||
603 | /* Return true iff TYPE1 inherits from TYPE2. */ | |
604 | ||
605 | int | |
0a2f0c54 | 606 | inherits_from_p (tree type1, tree type2) |
e04a16fb AG |
607 | { |
608 | while (type1 != NULL_TREE && TREE_CODE (type1) == RECORD_TYPE) | |
609 | { | |
610 | if (type1 == type2) | |
611 | return 1; | |
1b70949a | 612 | |
d35310e3 PB |
613 | if (! CLASS_LOADED_P (type1)) |
614 | load_class (type1, 1); | |
1b70949a RM |
615 | |
616 | type1 = maybe_layout_super_class (CLASSTYPE_SUPER (type1), type1); | |
e04a16fb AG |
617 | } |
618 | return 0; | |
619 | } | |
620 | ||
c2952b01 APB |
621 | /* Return a 1 iff TYPE1 is an enclosing context for TYPE2 */ |
622 | ||
623 | int | |
0a2f0c54 | 624 | enclosing_context_p (tree type1, tree type2) |
c2952b01 APB |
625 | { |
626 | if (!INNER_CLASS_TYPE_P (type2)) | |
627 | return 0; | |
628 | ||
629 | for (type2 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2))); | |
630 | type2; | |
631 | type2 = (INNER_CLASS_TYPE_P (type2) ? | |
632 | TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2))) : NULL_TREE)) | |
633 | { | |
634 | if (type2 == type1) | |
635 | return 1; | |
636 | } | |
637 | ||
638 | return 0; | |
639 | } | |
640 | ||
d3ecb597 BM |
641 | |
642 | /* Return 1 iff TYPE1 and TYPE2 share a common enclosing class, regardless of | |
643 | nesting level. */ | |
152de068 | 644 | |
fe0b9fb5 RM |
645 | int |
646 | common_enclosing_context_p (tree type1, tree type2) | |
d3ecb597 | 647 | { |
9ee226ef | 648 | while (type1) |
d3ecb597 BM |
649 | { |
650 | tree current; | |
651 | for (current = type2; current; | |
652 | current = (INNER_CLASS_TYPE_P (current) ? | |
653 | TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current))) : | |
654 | NULL_TREE)) | |
655 | if (type1 == current) | |
656 | return 1; | |
9ee226ef BM |
657 | |
658 | if (INNER_CLASS_TYPE_P (type1)) | |
659 | type1 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))); | |
660 | else | |
661 | break; | |
d3ecb597 BM |
662 | } |
663 | return 0; | |
664 | } | |
665 | ||
666 | /* Return 1 iff there exists a common enclosing "this" between TYPE1 | |
667 | and TYPE2, without crossing any static context. */ | |
668 | ||
669 | int | |
670 | common_enclosing_instance_p (tree type1, tree type2) | |
152de068 | 671 | { |
4dbf4496 | 672 | if (!PURE_INNER_CLASS_TYPE_P (type1) || !PURE_INNER_CLASS_TYPE_P (type2)) |
152de068 APB |
673 | return 0; |
674 | ||
675 | for (type1 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))); type1; | |
676 | type1 = (PURE_INNER_CLASS_TYPE_P (type1) ? | |
677 | TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))) : NULL_TREE)) | |
678 | { | |
679 | tree current; | |
680 | for (current = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2))); current; | |
681 | current = (PURE_INNER_CLASS_TYPE_P (current) ? | |
682 | TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current))) : | |
683 | NULL_TREE)) | |
684 | if (type1 == current) | |
685 | return 1; | |
686 | } | |
687 | return 0; | |
688 | } | |
689 | ||
e04a16fb AG |
690 | /* Add INTERFACE_CLASS to THIS_CLASS iff INTERFACE_CLASS can't be |
691 | found in THIS_CLASS. Returns NULL_TREE upon success, INTERFACE_CLASS | |
692 | if attempt is made to add it twice. */ | |
693 | ||
694 | tree | |
0a2f0c54 | 695 | maybe_add_interface (tree this_class, tree interface_class) |
e04a16fb | 696 | { |
fa743e8c | 697 | tree binfo, base_binfo; |
e04a16fb | 698 | int i; |
fa743e8c NS |
699 | |
700 | for (binfo = TYPE_BINFO (this_class), i = 0; | |
701 | BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) | |
702 | if (BINFO_TYPE (base_binfo) == interface_class) | |
703 | return interface_class; | |
704 | add_interface (this_class, interface_class); | |
e04a16fb AG |
705 | return NULL_TREE; |
706 | } | |
707 | ||
708 | /* Add the INTERFACE_CLASS as one of the interfaces of THIS_CLASS. */ | |
709 | ||
710 | void | |
0a2f0c54 | 711 | add_interface (tree this_class, tree interface_class) |
e04a16fb | 712 | { |
fa743e8c NS |
713 | tree interface_binfo = make_tree_binfo (0); |
714 | ||
715 | BINFO_TYPE (interface_binfo) = interface_class; | |
716 | BINFO_OFFSET (interface_binfo) = integer_zero_node; | |
717 | BINFO_VPTR_FIELD (interface_binfo) = integer_zero_node; | |
718 | BINFO_VIRTUAL_P (interface_binfo) = 1; | |
719 | ||
720 | BINFO_BASE_APPEND (TYPE_BINFO (this_class), interface_binfo); | |
e04a16fb AG |
721 | } |
722 | ||
4bcde32e | 723 | static tree |
0a2f0c54 | 724 | build_java_method_type (tree fntype, tree this_class, int access_flags) |
e04a16fb AG |
725 | { |
726 | if (access_flags & ACC_STATIC) | |
727 | return fntype; | |
e6b7893e AH |
728 | fntype = build_method_type (this_class, fntype); |
729 | ||
730 | /* We know that arg 1 of every nonstatic method is non-null; tell | |
731 | the back-end so. */ | |
732 | TYPE_ATTRIBUTES (fntype) = (tree_cons | |
733 | (get_identifier ("nonnull"), | |
734 | tree_cons (NULL_TREE, | |
735 | build_int_cst (NULL_TREE, 1), | |
736 | NULL_TREE), | |
737 | TYPE_ATTRIBUTES (fntype))); | |
738 | return fntype; | |
e04a16fb AG |
739 | } |
740 | ||
3e603aef DD |
741 | void |
742 | java_hide_decl (tree decl ATTRIBUTE_UNUSED) | |
696fbee7 | 743 | { |
c1331fd4 | 744 | #ifdef HAVE_GAS_HIDDEN |
696fbee7 AH |
745 | DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; |
746 | DECL_VISIBILITY_SPECIFIED (decl) = 1; | |
c1331fd4 | 747 | #endif |
696fbee7 AH |
748 | } |
749 | ||
e04a16fb | 750 | tree |
0a2f0c54 | 751 | add_method_1 (tree this_class, int access_flags, tree name, tree function_type) |
e04a16fb AG |
752 | { |
753 | tree method_type, fndecl; | |
e04a16fb AG |
754 | |
755 | method_type = build_java_method_type (function_type, | |
c02ebb18 | 756 | this_class, access_flags); |
e04a16fb AG |
757 | |
758 | fndecl = build_decl (FUNCTION_DECL, name, method_type); | |
c02ebb18 | 759 | DECL_CONTEXT (fndecl) = this_class; |
e04a16fb AG |
760 | |
761 | DECL_LANG_SPECIFIC (fndecl) | |
a92cb0c3 | 762 | = ggc_alloc_cleared (sizeof (struct lang_decl)); |
e2500fed | 763 | DECL_LANG_SPECIFIC (fndecl)->desc = LANG_DECL_FUNC; |
e04a16fb | 764 | |
3ff9925c | 765 | /* Initialize the static initializer test table. */ |
e2500fed GK |
766 | |
767 | DECL_FUNCTION_INIT_TEST_TABLE (fndecl) = | |
768 | java_treetreehash_create (10, 1); | |
3ff9925c | 769 | |
4009bb7d APB |
770 | /* Initialize the initialized (static) class table. */ |
771 | if (access_flags & ACC_STATIC) | |
e2500fed GK |
772 | DECL_FUNCTION_INITIALIZED_CLASS_TABLE (fndecl) = |
773 | htab_create_ggc (50, htab_hash_pointer, htab_eq_pointer, NULL); | |
4009bb7d | 774 | |
c02ebb18 ZW |
775 | TREE_CHAIN (fndecl) = TYPE_METHODS (this_class); |
776 | TYPE_METHODS (this_class) = fndecl; | |
e04a16fb | 777 | |
837edd5f GK |
778 | /* If pointers to member functions use the least significant bit to |
779 | indicate whether a function is virtual, ensure a pointer | |
780 | to this function will have that bit clear. */ | |
781 | if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn | |
782 | && !(access_flags & ACC_STATIC) | |
783 | && DECL_ALIGN (fndecl) < 2 * BITS_PER_UNIT) | |
784 | DECL_ALIGN (fndecl) = 2 * BITS_PER_UNIT; | |
785 | ||
eec87542 HB |
786 | /* Notice that this is a finalizer and update the class type |
787 | accordingly. This is used to optimize instance allocation. */ | |
788 | if (name == finalize_identifier_node | |
789 | && TREE_TYPE (function_type) == void_type_node | |
790 | && TREE_VALUE (TYPE_ARG_TYPES (function_type)) == void_type_node) | |
c02ebb18 | 791 | HAS_FINALIZER_P (this_class) = 1; |
eec87542 | 792 | |
e04a16fb AG |
793 | if (access_flags & ACC_PUBLIC) METHOD_PUBLIC (fndecl) = 1; |
794 | if (access_flags & ACC_PROTECTED) METHOD_PROTECTED (fndecl) = 1; | |
8119c720 APB |
795 | if (access_flags & ACC_PRIVATE) |
796 | METHOD_PRIVATE (fndecl) = DECL_INLINE (fndecl) = 1; | |
7145d9fe TT |
797 | if (access_flags & ACC_NATIVE) |
798 | { | |
799 | METHOD_NATIVE (fndecl) = 1; | |
800 | DECL_EXTERNAL (fndecl) = 1; | |
801 | } | |
2631dfdd AH |
802 | else |
803 | /* FNDECL is external unless we are compiling it into this object | |
804 | file. */ | |
805 | DECL_EXTERNAL (fndecl) = CLASS_FROM_CURRENTLY_COMPILED_P (this_class) == 0; | |
8119c720 APB |
806 | if (access_flags & ACC_STATIC) |
807 | METHOD_STATIC (fndecl) = DECL_INLINE (fndecl) = 1; | |
808 | if (access_flags & ACC_FINAL) | |
809 | METHOD_FINAL (fndecl) = DECL_INLINE (fndecl) = 1; | |
e04a16fb AG |
810 | if (access_flags & ACC_SYNCHRONIZED) METHOD_SYNCHRONIZED (fndecl) = 1; |
811 | if (access_flags & ACC_ABSTRACT) METHOD_ABSTRACT (fndecl) = 1; | |
6b6294f1 | 812 | if (access_flags & ACC_STRICT) METHOD_STRICTFP (fndecl) = 1; |
97b8365c TT |
813 | if (access_flags & ACC_SYNTHETIC) DECL_ARTIFICIAL (fndecl) = 1; |
814 | if (access_flags & ACC_BRIDGE) METHOD_BRIDGE (fndecl) = 1; | |
815 | if (access_flags & ACC_VARARGS) METHOD_VARARGS (fndecl) = 1; | |
e04a16fb AG |
816 | return fndecl; |
817 | } | |
818 | ||
819 | /* Add a method to THIS_CLASS. | |
820 | The method's name is NAME. | |
821 | Its signature (mangled type) is METHOD_SIG (an IDENTIFIER_NODE). */ | |
822 | ||
823 | tree | |
0a2f0c54 | 824 | add_method (tree this_class, int access_flags, tree name, tree method_sig) |
e04a16fb | 825 | { |
d640220c | 826 | tree function_type, fndecl; |
400500c4 RK |
827 | const unsigned char *sig |
828 | = (const unsigned char *) IDENTIFIER_POINTER (method_sig); | |
829 | ||
e04a16fb | 830 | if (sig[0] != '(') |
400500c4 RK |
831 | fatal_error ("bad method signature"); |
832 | ||
e04a16fb | 833 | function_type = get_type_from_signature (method_sig); |
c02ebb18 | 834 | fndecl = add_method_1 (this_class, access_flags, name, function_type); |
e04a16fb | 835 | set_java_signature (TREE_TYPE (fndecl), method_sig); |
e04a16fb AG |
836 | return fndecl; |
837 | } | |
838 | ||
839 | tree | |
0a2f0c54 | 840 | add_field (tree class, tree name, tree field_type, int flags) |
e04a16fb AG |
841 | { |
842 | int is_static = (flags & ACC_STATIC) != 0; | |
843 | tree field; | |
e04a16fb | 844 | field = build_decl (is_static ? VAR_DECL : FIELD_DECL, name, field_type); |
e04a16fb AG |
845 | TREE_CHAIN (field) = TYPE_FIELDS (class); |
846 | TYPE_FIELDS (class) = field; | |
847 | DECL_CONTEXT (field) = class; | |
97b8365c | 848 | MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (field); |
e04a16fb AG |
849 | |
850 | if (flags & ACC_PUBLIC) FIELD_PUBLIC (field) = 1; | |
851 | if (flags & ACC_PROTECTED) FIELD_PROTECTED (field) = 1; | |
852 | if (flags & ACC_PRIVATE) FIELD_PRIVATE (field) = 1; | |
853 | if (flags & ACC_FINAL) FIELD_FINAL (field) = 1; | |
572f9e47 AH |
854 | if (flags & ACC_VOLATILE) |
855 | { | |
856 | FIELD_VOLATILE (field) = 1; | |
857 | TREE_THIS_VOLATILE (field) = 1; | |
858 | } | |
e04a16fb | 859 | if (flags & ACC_TRANSIENT) FIELD_TRANSIENT (field) = 1; |
97b8365c TT |
860 | if (flags & ACC_ENUM) FIELD_ENUM (field) = 1; |
861 | if (flags & ACC_SYNTHETIC) FIELD_SYNTHETIC (field) = 1; | |
e04a16fb AG |
862 | if (is_static) |
863 | { | |
864 | FIELD_STATIC (field) = 1; | |
a7303141 PB |
865 | /* Always make field externally visible. This is required so |
866 | that native methods can always access the field. */ | |
867 | TREE_PUBLIC (field) = 1; | |
696fbee7 AH |
868 | /* Hide everything that shouldn't be visible outside a DSO. */ |
869 | if (flag_indirect_classes | |
870 | || (FIELD_PRIVATE (field))) | |
3e603aef | 871 | java_hide_decl (field); |
97b8365c TT |
872 | /* Considered external unless we are compiling it into this |
873 | object file. */ | |
874 | DECL_EXTERNAL (field) = (is_compiled_class (class) != 2); | |
e04a16fb | 875 | } |
f0c75752 | 876 | |
e04a16fb AG |
877 | return field; |
878 | } | |
879 | ||
880 | /* Associate a constant value CONSTANT with VAR_DECL FIELD. */ | |
881 | ||
882 | void | |
0a2f0c54 | 883 | set_constant_value (tree field, tree constant) |
e04a16fb AG |
884 | { |
885 | if (field == NULL_TREE) | |
5c498b10 DD |
886 | warning (OPT_Wattributes, |
887 | "misplaced ConstantValue attribute (not in any field)"); | |
e04a16fb | 888 | else if (DECL_INITIAL (field) != NULL_TREE) |
5c498b10 DD |
889 | warning (OPT_Wattributes, |
890 | "duplicate ConstantValue attribute for field '%s'", | |
e04a16fb AG |
891 | IDENTIFIER_POINTER (DECL_NAME (field))); |
892 | else | |
493d561d APB |
893 | { |
894 | DECL_INITIAL (field) = constant; | |
1b9ee723 PB |
895 | if (TREE_TYPE (constant) != TREE_TYPE (field) |
896 | && ! (TREE_TYPE (constant) == int_type_node | |
897 | && INTEGRAL_TYPE_P (TREE_TYPE (field)) | |
289b57ee PB |
898 | && TYPE_PRECISION (TREE_TYPE (field)) <= 32) |
899 | && ! (TREE_TYPE (constant) == utf8const_ptr_type | |
900 | && TREE_TYPE (field) == string_ptr_type_node)) | |
901 | error ("ConstantValue attribute of field '%s' has wrong type", | |
1b9ee723 | 902 | IDENTIFIER_POINTER (DECL_NAME (field))); |
493d561d | 903 | } |
e04a16fb AG |
904 | } |
905 | ||
e04a16fb AG |
906 | /* Calculate a hash value for a string encoded in Utf8 format. |
907 | * This returns the same hash value as specified for java.lang.String.hashCode. | |
908 | */ | |
909 | ||
4bcde32e | 910 | static int32 |
0a2f0c54 | 911 | hashUtf8String (const char *str, int len) |
e04a16fb | 912 | { |
3a976c72 KH |
913 | const unsigned char* ptr = (const unsigned char*) str; |
914 | const unsigned char *limit = ptr + len; | |
e04a16fb AG |
915 | int32 hash = 0; |
916 | for (; ptr < limit;) | |
917 | { | |
918 | int ch = UTF8_GET (ptr, limit); | |
919 | /* Updated specification from | |
920 | http://www.javasoft.com/docs/books/jls/clarify.html. */ | |
921 | hash = (31 * hash) + ch; | |
922 | } | |
923 | return hash; | |
924 | } | |
925 | ||
3e895978 | 926 | static GTY(()) tree utf8_decl_list = NULL_TREE; |
e04a16fb AG |
927 | |
928 | tree | |
0a2f0c54 | 929 | build_utf8_ref (tree name) |
e04a16fb | 930 | { |
c8e7d2e6 | 931 | const char * name_ptr = IDENTIFIER_POINTER(name); |
e04a16fb AG |
932 | int name_len = IDENTIFIER_LENGTH(name); |
933 | char buf[60]; | |
ab3a6dd6 | 934 | tree ctype, field = NULL_TREE, str_type, cinit, string; |
e04a16fb | 935 | static int utf8_count = 0; |
5667c33d | 936 | int name_hash; |
e04a16fb AG |
937 | tree ref = IDENTIFIER_UTF8_REF (name); |
938 | tree decl; | |
939 | if (ref != NULL_TREE) | |
940 | return ref; | |
941 | ||
e04a16fb AG |
942 | ctype = make_node (RECORD_TYPE); |
943 | str_type = build_prim_array_type (unsigned_byte_type_node, | |
944 | name_len + 1); /* Allow for final '\0'. */ | |
945 | PUSH_FIELD (ctype, field, "hash", unsigned_short_type_node); | |
946 | PUSH_FIELD (ctype, field, "length", unsigned_short_type_node); | |
947 | PUSH_FIELD (ctype, field, "data", str_type); | |
948 | FINISH_RECORD (ctype); | |
949 | START_RECORD_CONSTRUCTOR (cinit, ctype); | |
7e57923c | 950 | name_hash = hashUtf8String (name_ptr, name_len) & 0xFFFF; |
7d60be94 NS |
951 | PUSH_FIELD_VALUE (cinit, "hash", build_int_cst (NULL_TREE, name_hash)); |
952 | PUSH_FIELD_VALUE (cinit, "length", build_int_cst (NULL_TREE, name_len)); | |
7e57923c | 953 | string = build_string (name_len, name_ptr); |
e04a16fb AG |
954 | TREE_TYPE (string) = str_type; |
955 | PUSH_FIELD_VALUE (cinit, "data", string); | |
956 | FINISH_RECORD_CONSTRUCTOR (cinit); | |
99fd3aa5 | 957 | TREE_CONSTANT (cinit) = 1; |
e04a16fb | 958 | |
48187504 | 959 | /* Generate a unique-enough identifier. */ |
e04a16fb | 960 | sprintf(buf, "_Utf%d", ++utf8_count); |
e04a16fb AG |
961 | |
962 | decl = build_decl (VAR_DECL, get_identifier (buf), utf8const_type); | |
e04a16fb AG |
963 | TREE_STATIC (decl) = 1; |
964 | DECL_ARTIFICIAL (decl) = 1; | |
965 | DECL_IGNORED_P (decl) = 1; | |
966 | TREE_READONLY (decl) = 1; | |
99fd3aa5 | 967 | TREE_THIS_VOLATILE (decl) = 0; |
e04a16fb | 968 | DECL_INITIAL (decl) = cinit; |
eb9ec0d4 RO |
969 | |
970 | if (HAVE_GAS_SHF_MERGE) | |
971 | { | |
972 | int decl_size; | |
973 | /* Ensure decl_size is a multiple of utf8const_type's alignment. */ | |
974 | decl_size = (name_len + 5 + TYPE_ALIGN_UNIT (utf8const_type) - 1) | |
975 | & ~(TYPE_ALIGN_UNIT (utf8const_type) - 1); | |
976 | if (flag_merge_constants && decl_size < 256) | |
977 | { | |
978 | char buf[32]; | |
979 | int flags = (SECTION_OVERRIDE | |
980 | | SECTION_MERGE | (SECTION_ENTSIZE & decl_size)); | |
981 | sprintf (buf, ".rodata.jutf8.%d", decl_size); | |
d6b5193b | 982 | switch_to_section (get_section (buf, flags, NULL)); |
eb9ec0d4 RO |
983 | DECL_SECTION_NAME (decl) = build_string (strlen (buf), buf); |
984 | } | |
985 | } | |
986 | ||
e04a16fb AG |
987 | TREE_CHAIN (decl) = utf8_decl_list; |
988 | layout_decl (decl, 0); | |
989 | pushdecl (decl); | |
0e6df31e | 990 | rest_of_decl_compilation (decl, global_bindings_p (), 0); |
8a4a83ed | 991 | varpool_mark_needed_node (varpool_node (decl)); |
e04a16fb | 992 | utf8_decl_list = decl; |
e04a16fb AG |
993 | ref = build1 (ADDR_EXPR, utf8const_ptr_type, decl); |
994 | IDENTIFIER_UTF8_REF (name) = ref; | |
e04a16fb AG |
995 | return ref; |
996 | } | |
997 | ||
90471585 AH |
998 | /* Like build_class_ref, but instead of a direct reference generate a |
999 | pointer into the constant pool. */ | |
1000 | ||
1001 | static tree | |
1002 | build_indirect_class_ref (tree type) | |
1003 | { | |
1004 | int index; | |
1005 | tree cl; | |
1006 | index = alloc_class_constant (type); | |
1007 | cl = build_ref_from_constant_pool (index); | |
6de9cd9a | 1008 | return convert (promote_type (class_ptr_type), cl); |
90471585 AH |
1009 | } |
1010 | ||
621ae65d AH |
1011 | static tree |
1012 | build_static_class_ref (tree type) | |
1013 | { | |
1014 | tree decl_name, decl, ref; | |
1015 | ||
1016 | if (TYPE_SIZE (type) == error_mark_node) | |
1017 | return null_pointer_node; | |
1018 | decl_name = identifier_subst (DECL_NAME (TYPE_NAME (type)), | |
1019 | "", '/', '/', ".class$$"); | |
1020 | decl = IDENTIFIER_GLOBAL_VALUE (decl_name); | |
1021 | if (decl == NULL_TREE) | |
1022 | { | |
1023 | decl = build_decl (VAR_DECL, decl_name, class_type_node); | |
1024 | TREE_STATIC (decl) = 1; | |
1025 | if (! flag_indirect_classes) | |
696fbee7 AH |
1026 | { |
1027 | TREE_PUBLIC (decl) = 1; | |
1028 | if (CLASS_PRIVATE (TYPE_NAME (type))) | |
3e603aef | 1029 | java_hide_decl (decl); |
696fbee7 | 1030 | } |
621ae65d AH |
1031 | DECL_IGNORED_P (decl) = 1; |
1032 | DECL_ARTIFICIAL (decl) = 1; | |
1033 | if (is_compiled_class (type) == 1) | |
1034 | DECL_EXTERNAL (decl) = 1; | |
1035 | MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); | |
1036 | DECL_CLASS_FIELD_P (decl) = 1; | |
1037 | DECL_CONTEXT (decl) = type; | |
1038 | ||
1039 | /* ??? We want to preserve the DECL_CONTEXT we set just above, | |
1040 | that that means not calling pushdecl_top_level. */ | |
1041 | IDENTIFIER_GLOBAL_VALUE (decl_name) = decl; | |
1042 | } | |
1043 | ||
1044 | ref = build1 (ADDR_EXPR, class_ptr_type, decl); | |
1045 | return ref; | |
1046 | } | |
1047 | ||
1048 | static tree | |
1049 | build_classdollar_field (tree type) | |
1050 | { | |
1051 | tree decl_name = identifier_subst (DECL_NAME (TYPE_NAME (type)), | |
1052 | "", '/', '/', ".class$"); | |
1053 | tree decl = IDENTIFIER_GLOBAL_VALUE (decl_name); | |
1054 | ||
1055 | if (decl == NULL_TREE) | |
1056 | { | |
1057 | decl | |
1058 | = build_decl (VAR_DECL, decl_name, | |
1059 | (build_type_variant | |
1060 | (build_pointer_type | |
1061 | (build_type_variant (class_type_node, | |
1062 | /* const */ 1, 0)), | |
1063 | /* const */ 1, 0))); | |
1064 | TREE_STATIC (decl) = 1; | |
621ae65d AH |
1065 | TREE_CONSTANT (decl) = 1; |
1066 | TREE_READONLY (decl) = 1; | |
1067 | TREE_PUBLIC (decl) = 1; | |
3e603aef | 1068 | java_hide_decl (decl); |
621ae65d AH |
1069 | DECL_IGNORED_P (decl) = 1; |
1070 | DECL_ARTIFICIAL (decl) = 1; | |
1071 | MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); | |
1072 | IDENTIFIER_GLOBAL_VALUE (decl_name) = decl; | |
1073 | DECL_CLASS_FIELD_P (decl) = 1; | |
1074 | DECL_CONTEXT (decl) = type; | |
1075 | } | |
1076 | ||
1077 | return decl; | |
1078 | } | |
1079 | ||
165a0dc3 | 1080 | /* Create a local variable that holds the current class$. */ |
b4e18eee AH |
1081 | |
1082 | void | |
1083 | cache_this_class_ref (tree fndecl) | |
1084 | { | |
1085 | if (optimize) | |
1086 | { | |
1087 | tree classdollar_field; | |
1088 | if (flag_indirect_classes) | |
1089 | classdollar_field = build_classdollar_field (output_class); | |
1090 | else | |
1091 | classdollar_field = build_static_class_ref (output_class); | |
1092 | ||
1093 | this_classdollar = build_decl (VAR_DECL, NULL_TREE, | |
1094 | TREE_TYPE (classdollar_field)); | |
1095 | ||
1096 | java_add_local_var (this_classdollar); | |
1097 | java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (this_classdollar), | |
1098 | this_classdollar, classdollar_field)); | |
1099 | } | |
1100 | else | |
1101 | this_classdollar = build_classdollar_field (output_class); | |
1102 | ||
1103 | /* Prepend class initialization for static methods reachable from | |
1104 | other classes. */ | |
1105 | if (METHOD_STATIC (fndecl) | |
1106 | && (! METHOD_PRIVATE (fndecl) | |
1107 | || INNER_CLASS_P (DECL_CONTEXT (fndecl))) | |
1108 | && ! DECL_CLINIT_P (fndecl) | |
1109 | && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (fndecl)))) | |
1110 | { | |
5039610b SL |
1111 | tree init = build_call_expr (soft_initclass_node, 1, |
1112 | this_classdollar); | |
b4e18eee AH |
1113 | java_add_stmt (init); |
1114 | } | |
1115 | } | |
1116 | ||
56c9f04b AH |
1117 | /* Remove the reference to the local variable that holds the current |
1118 | class$. */ | |
1119 | ||
1120 | void | |
1121 | uncache_this_class_ref (tree fndecl ATTRIBUTE_UNUSED) | |
1122 | { | |
1123 | this_classdollar = build_classdollar_field (output_class); | |
1124 | } | |
1125 | ||
e04a16fb AG |
1126 | /* Build a reference to the class TYPE. |
1127 | Also handles primitive types and array types. */ | |
1128 | ||
1129 | tree | |
0a2f0c54 | 1130 | build_class_ref (tree type) |
e04a16fb AG |
1131 | { |
1132 | int is_compiled = is_compiled_class (type); | |
1133 | if (is_compiled) | |
1134 | { | |
621ae65d | 1135 | tree ref, decl; |
e04a16fb AG |
1136 | if (TREE_CODE (type) == POINTER_TYPE) |
1137 | type = TREE_TYPE (type); | |
90471585 | 1138 | |
e0f391dd RH |
1139 | if (flag_indirect_dispatch |
1140 | && type != output_class | |
1141 | && TREE_CODE (type) == RECORD_TYPE) | |
90471585 AH |
1142 | return build_indirect_class_ref (type); |
1143 | ||
621ae65d | 1144 | if (type == output_class && flag_indirect_classes) |
25e8b6ce TT |
1145 | { |
1146 | /* This can be NULL if we see a JNI stub before we see any | |
1147 | other method. */ | |
1148 | if (! this_classdollar) | |
1149 | this_classdollar = build_classdollar_field (output_class); | |
1150 | return this_classdollar; | |
1151 | } | |
621ae65d | 1152 | |
e04a16fb | 1153 | if (TREE_CODE (type) == RECORD_TYPE) |
621ae65d | 1154 | return build_static_class_ref (type); |
e04a16fb AG |
1155 | else |
1156 | { | |
c8e7d2e6 | 1157 | const char *name; |
621ae65d | 1158 | tree decl_name; |
66d88624 | 1159 | char buffer[25]; |
e04a16fb AG |
1160 | decl_name = TYPE_NAME (type); |
1161 | if (TREE_CODE (decl_name) == TYPE_DECL) | |
1162 | decl_name = DECL_NAME (decl_name); | |
1163 | name = IDENTIFIER_POINTER (decl_name); | |
1164 | if (strncmp (name, "promoted_", 9) == 0) | |
1165 | name += 9; | |
66d88624 | 1166 | sprintf (buffer, "_Jv_%sClass", name); |
e04a16fb AG |
1167 | decl_name = get_identifier (buffer); |
1168 | decl = IDENTIFIER_GLOBAL_VALUE (decl_name); | |
1169 | if (decl == NULL_TREE) | |
1170 | { | |
e04a16fb AG |
1171 | decl = build_decl (VAR_DECL, decl_name, class_type_node); |
1172 | TREE_STATIC (decl) = 1; | |
1173 | TREE_PUBLIC (decl) = 1; | |
f44fefca | 1174 | DECL_EXTERNAL (decl) = 1; |
6744f400 | 1175 | DECL_ARTIFICIAL (decl) = 1; |
e04a16fb | 1176 | pushdecl_top_level (decl); |
e04a16fb AG |
1177 | } |
1178 | } | |
1179 | ||
1180 | ref = build1 (ADDR_EXPR, class_ptr_type, decl); | |
1181 | return ref; | |
1182 | } | |
1183 | else | |
90471585 | 1184 | return build_indirect_class_ref (type); |
e04a16fb AG |
1185 | } |
1186 | ||
2c80f015 AH |
1187 | /* Create a local statically allocated variable that will hold a |
1188 | pointer to a static field. */ | |
1189 | ||
1190 | static tree | |
1191 | build_fieldref_cache_entry (int index, tree fdecl ATTRIBUTE_UNUSED) | |
1192 | { | |
1193 | tree decl, decl_name; | |
1194 | const char *name = IDENTIFIER_POINTER (mangled_classname ("_cpool_", output_class)); | |
1195 | char *buf = alloca (strlen (name) + 20); | |
1196 | sprintf (buf, "%s_%d_ref", name, index); | |
1197 | decl_name = get_identifier (buf); | |
1198 | decl = IDENTIFIER_GLOBAL_VALUE (decl_name); | |
1199 | if (decl == NULL_TREE) | |
1200 | { | |
1201 | decl = build_decl (VAR_DECL, decl_name, ptr_type_node); | |
1202 | TREE_STATIC (decl) = 1; | |
1203 | TREE_PUBLIC (decl) = 0; | |
1204 | DECL_EXTERNAL (decl) = 0; | |
1205 | DECL_ARTIFICIAL (decl) = 1; | |
8a71d22b | 1206 | DECL_IGNORED_P (decl) = 1; |
2c80f015 AH |
1207 | pushdecl_top_level (decl); |
1208 | } | |
1209 | return decl; | |
1210 | } | |
1211 | ||
e04a16fb | 1212 | tree |
0a2f0c54 | 1213 | build_static_field_ref (tree fdecl) |
e04a16fb AG |
1214 | { |
1215 | tree fclass = DECL_CONTEXT (fdecl); | |
1216 | int is_compiled = is_compiled_class (fclass); | |
d3ab697b | 1217 | |
c2c98445 | 1218 | /* Allow static final fields to fold to a constant. When using |
4267db98 TT |
1219 | -findirect-dispatch, we simply never do this folding if compiling |
1220 | from .class; in the .class file constants will be referred to via | |
1221 | the constant pool. */ | |
279e32c9 | 1222 | if (!flag_indirect_dispatch |
4267db98 TT |
1223 | && (is_compiled |
1224 | || (FIELD_FINAL (fdecl) && DECL_INITIAL (fdecl) != NULL_TREE | |
1225 | && (JSTRING_TYPE_P (TREE_TYPE (fdecl)) | |
1226 | || JNUMERIC_TYPE_P (TREE_TYPE (fdecl))) | |
1227 | && TREE_CONSTANT (DECL_INITIAL (fdecl))))) | |
e04a16fb | 1228 | { |
e0f391dd RH |
1229 | if (is_compiled == 1) |
1230 | DECL_EXTERNAL (fdecl) = 1; | |
9dfc2ec2 | 1231 | } |
2c80f015 | 1232 | else |
e04a16fb | 1233 | { |
2c80f015 AH |
1234 | /* Generate a CONSTANT_FieldRef for FDECL in the constant pool |
1235 | and a class local static variable CACHE_ENTRY, then | |
1236 | ||
1237 | *(fdecl **)((__builtin_expect (cache_entry == null, false)) | |
1238 | ? cache_entry = _Jv_ResolvePoolEntry (output_class, cpool_index) | |
1239 | : cache_entry) | |
1240 | ||
1241 | This can mostly be optimized away, so that the usual path is a | |
1242 | load followed by a test and branch. _Jv_ResolvePoolEntry is | |
1243 | only called once for each constant pool entry. | |
1244 | ||
1245 | There is an optimization that we don't do: at the start of a | |
1246 | method, create a local copy of CACHE_ENTRY and use that instead. | |
1247 | ||
1248 | */ | |
1249 | ||
1250 | int cpool_index = alloc_constant_fieldref (output_class, fdecl); | |
1251 | tree cache_entry = build_fieldref_cache_entry (cpool_index, fdecl); | |
5039610b SL |
1252 | tree test |
1253 | = build_call_expr (built_in_decls[BUILT_IN_EXPECT], 2, | |
1254 | build2 (EQ_EXPR, boolean_type_node, | |
1255 | cache_entry, null_pointer_node), | |
1256 | boolean_false_node); | |
2c80f015 AH |
1257 | tree cpool_index_cst = build_int_cst (NULL_TREE, cpool_index); |
1258 | tree init | |
5039610b SL |
1259 | = build_call_expr (soft_resolvepoolentry_node, 2, |
1260 | build_class_ref (output_class), | |
1261 | cpool_index_cst); | |
2c80f015 AH |
1262 | init = build2 (MODIFY_EXPR, ptr_type_node, cache_entry, init); |
1263 | init = build3 (COND_EXPR, ptr_type_node, test, init, cache_entry); | |
1264 | init = fold_convert (build_pointer_type (TREE_TYPE (fdecl)), init); | |
1265 | fdecl = build1 (INDIRECT_REF, TREE_TYPE (fdecl), init); | |
e04a16fb | 1266 | } |
2c80f015 | 1267 | return fdecl; |
e04a16fb AG |
1268 | } |
1269 | ||
1270 | int | |
0a2f0c54 | 1271 | get_access_flags_from_decl (tree decl) |
e04a16fb AG |
1272 | { |
1273 | int access_flags = 0; | |
1274 | if (TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL) | |
1275 | { | |
1276 | if (FIELD_STATIC (decl)) | |
1277 | access_flags |= ACC_STATIC; | |
1278 | if (FIELD_PUBLIC (decl)) | |
1279 | access_flags |= ACC_PUBLIC; | |
1280 | if (FIELD_PROTECTED (decl)) | |
1281 | access_flags |= ACC_PROTECTED; | |
1282 | if (FIELD_PRIVATE (decl)) | |
1283 | access_flags |= ACC_PRIVATE; | |
1284 | if (FIELD_FINAL (decl)) | |
1285 | access_flags |= ACC_FINAL; | |
1286 | if (FIELD_VOLATILE (decl)) | |
1287 | access_flags |= ACC_VOLATILE; | |
1288 | if (FIELD_TRANSIENT (decl)) | |
1289 | access_flags |= ACC_TRANSIENT; | |
97b8365c TT |
1290 | if (FIELD_ENUM (decl)) |
1291 | access_flags |= ACC_ENUM; | |
1292 | if (FIELD_SYNTHETIC (decl)) | |
1293 | access_flags |= ACC_SYNTHETIC; | |
e04a16fb AG |
1294 | return access_flags; |
1295 | } | |
1296 | if (TREE_CODE (decl) == TYPE_DECL) | |
1297 | { | |
1298 | if (CLASS_PUBLIC (decl)) | |
1299 | access_flags |= ACC_PUBLIC; | |
1300 | if (CLASS_FINAL (decl)) | |
1301 | access_flags |= ACC_FINAL; | |
1302 | if (CLASS_SUPER (decl)) | |
1303 | access_flags |= ACC_SUPER; | |
1304 | if (CLASS_INTERFACE (decl)) | |
1305 | access_flags |= ACC_INTERFACE; | |
1306 | if (CLASS_ABSTRACT (decl)) | |
1307 | access_flags |= ACC_ABSTRACT; | |
c2952b01 APB |
1308 | if (CLASS_STATIC (decl)) |
1309 | access_flags |= ACC_STATIC; | |
4dbf4496 APB |
1310 | if (CLASS_PRIVATE (decl)) |
1311 | access_flags |= ACC_PRIVATE; | |
1312 | if (CLASS_PROTECTED (decl)) | |
1313 | access_flags |= ACC_PROTECTED; | |
6b6294f1 TT |
1314 | if (CLASS_STRICTFP (decl)) |
1315 | access_flags |= ACC_STRICT; | |
97b8365c TT |
1316 | if (CLASS_ENUM (decl)) |
1317 | access_flags |= ACC_ENUM; | |
1318 | if (CLASS_SYNTHETIC (decl)) | |
1319 | access_flags |= ACC_SYNTHETIC; | |
1320 | if (CLASS_ANNOTATION (decl)) | |
1321 | access_flags |= ACC_ANNOTATION; | |
e04a16fb AG |
1322 | return access_flags; |
1323 | } | |
1324 | if (TREE_CODE (decl) == FUNCTION_DECL) | |
1325 | { | |
1326 | if (METHOD_PUBLIC (decl)) | |
1327 | access_flags |= ACC_PUBLIC; | |
1328 | if (METHOD_PRIVATE (decl)) | |
1329 | access_flags |= ACC_PRIVATE; | |
1330 | if (METHOD_PROTECTED (decl)) | |
1331 | access_flags |= ACC_PROTECTED; | |
1332 | if (METHOD_STATIC (decl)) | |
1333 | access_flags |= ACC_STATIC; | |
1334 | if (METHOD_FINAL (decl)) | |
1335 | access_flags |= ACC_FINAL; | |
1336 | if (METHOD_SYNCHRONIZED (decl)) | |
1337 | access_flags |= ACC_SYNCHRONIZED; | |
1338 | if (METHOD_NATIVE (decl)) | |
1339 | access_flags |= ACC_NATIVE; | |
1340 | if (METHOD_ABSTRACT (decl)) | |
1341 | access_flags |= ACC_ABSTRACT; | |
6b6294f1 TT |
1342 | if (METHOD_STRICTFP (decl)) |
1343 | access_flags |= ACC_STRICT; | |
aecf4109 TT |
1344 | if (METHOD_INVISIBLE (decl)) |
1345 | access_flags |= ACC_INVISIBLE; | |
97b8365c TT |
1346 | if (DECL_ARTIFICIAL (decl)) |
1347 | access_flags |= ACC_SYNTHETIC; | |
1348 | if (METHOD_BRIDGE (decl)) | |
1349 | access_flags |= ACC_BRIDGE; | |
1350 | if (METHOD_VARARGS (decl)) | |
1351 | access_flags |= ACC_VARARGS; | |
e04a16fb AG |
1352 | return access_flags; |
1353 | } | |
ab184b2a | 1354 | gcc_unreachable (); |
e04a16fb AG |
1355 | } |
1356 | ||
65e9700c BM |
1357 | static GTY (()) int alias_labelno = 0; |
1358 | ||
1359 | /* Create a private alias for METHOD. Using this alias instead of the method | |
1360 | decl ensures that ncode entries in the method table point to the real function | |
1361 | at runtime, not a PLT entry. */ | |
1362 | ||
1363 | static tree | |
1364 | make_local_function_alias (tree method) | |
1365 | { | |
1366 | #ifdef ASM_OUTPUT_DEF | |
1367 | tree alias; | |
1368 | ||
1369 | const char *method_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method)); | |
1370 | char *name = alloca (strlen (method_name) + 2); | |
1371 | char *buf = alloca (strlen (method_name) + 128); | |
1372 | ||
1373 | /* Only create aliases for local functions. */ | |
1374 | if (DECL_EXTERNAL (method)) | |
1375 | return method; | |
1376 | ||
1377 | /* Prefix method_name with 'L' for the alias label. */ | |
1378 | *name = 'L'; | |
1379 | strcpy (name + 1, method_name); | |
1380 | ||
1381 | ASM_GENERATE_INTERNAL_LABEL (buf, name, alias_labelno++); | |
1382 | alias = build_decl (FUNCTION_DECL, get_identifier (buf), | |
1383 | TREE_TYPE (method)); | |
1384 | DECL_CONTEXT (alias) = NULL; | |
1385 | TREE_READONLY (alias) = TREE_READONLY (method); | |
1386 | TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (method); | |
1387 | TREE_PUBLIC (alias) = 0; | |
1388 | DECL_EXTERNAL (alias) = 0; | |
1389 | DECL_ARTIFICIAL (alias) = 1; | |
1390 | DECL_INLINE (alias) = 0; | |
1391 | DECL_INITIAL (alias) = error_mark_node; | |
1392 | TREE_ADDRESSABLE (alias) = 1; | |
1393 | TREE_USED (alias) = 1; | |
65e9700c BM |
1394 | TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1; |
1395 | if (!flag_syntax_only) | |
1396 | assemble_alias (alias, DECL_ASSEMBLER_NAME (method)); | |
1397 | return alias; | |
1398 | #else | |
1399 | return method; | |
1400 | #endif | |
1401 | } | |
1402 | ||
260ba9ce BM |
1403 | /** Make reflection data (_Jv_Field) for field FDECL. */ |
1404 | ||
4bcde32e | 1405 | static tree |
0a2f0c54 | 1406 | make_field_value (tree fdecl) |
e04a16fb | 1407 | { |
770ae6cc | 1408 | tree finit; |
665f2503 | 1409 | int flags; |
e04a16fb | 1410 | tree type = TREE_TYPE (fdecl); |
90471585 | 1411 | int resolved = is_compiled_class (type) && ! flag_indirect_dispatch; |
665f2503 | 1412 | |
e04a16fb AG |
1413 | START_RECORD_CONSTRUCTOR (finit, field_type_node); |
1414 | PUSH_FIELD_VALUE (finit, "name", build_utf8_ref (DECL_NAME (fdecl))); | |
1415 | if (resolved) | |
1416 | type = build_class_ref (type); | |
1417 | else | |
7e57923c AH |
1418 | { |
1419 | tree signature = build_java_signature (type); | |
770ae6cc | 1420 | |
7e57923c | 1421 | type = build_utf8_ref (unmangle_classname |
770ae6cc RK |
1422 | (IDENTIFIER_POINTER (signature), |
1423 | IDENTIFIER_LENGTH (signature))); | |
7e57923c | 1424 | } |
e04a16fb | 1425 | PUSH_FIELD_VALUE (finit, "type", type); |
770ae6cc | 1426 | |
e04a16fb AG |
1427 | flags = get_access_flags_from_decl (fdecl); |
1428 | if (! resolved) | |
1429 | flags |= 0x8000 /* FIELD_UNRESOLVED_FLAG */; | |
665f2503 | 1430 | |
7d60be94 | 1431 | PUSH_FIELD_VALUE (finit, "accflags", build_int_cst (NULL_TREE, flags)); |
665f2503 | 1432 | PUSH_FIELD_VALUE (finit, "bsize", TYPE_SIZE_UNIT (TREE_TYPE (fdecl))); |
665f2503 | 1433 | |
621ae65d AH |
1434 | { |
1435 | tree field_address = integer_zero_node; | |
b2ed63b4 AH |
1436 | if ((DECL_INITIAL (fdecl) || ! flag_indirect_classes) |
1437 | && FIELD_STATIC (fdecl)) | |
621ae65d AH |
1438 | field_address = build_address_of (fdecl); |
1439 | ||
1440 | PUSH_FIELD_VALUE | |
1441 | (finit, "info", | |
1442 | build_constructor_from_list (field_info_union_node, | |
1443 | build_tree_list | |
1444 | ((FIELD_STATIC (fdecl) | |
1445 | ? TREE_CHAIN (TYPE_FIELDS (field_info_union_node)) | |
1446 | : TYPE_FIELDS (field_info_union_node)), | |
1447 | (FIELD_STATIC (fdecl) | |
1448 | ? field_address | |
1449 | : byte_position (fdecl))))); | |
1450 | } | |
e04a16fb AG |
1451 | |
1452 | FINISH_RECORD_CONSTRUCTOR (finit); | |
1453 | return finit; | |
1454 | } | |
1455 | ||
260ba9ce BM |
1456 | /** Make reflection data (_Jv_Method) for method MDECL. */ |
1457 | ||
8e1f2d4c | 1458 | static tree |
0a2f0c54 | 1459 | make_method_value (tree mdecl) |
e04a16fb | 1460 | { |
66b461ce | 1461 | static int method_name_count = 0; |
e04a16fb | 1462 | tree minit; |
861ef928 | 1463 | tree index; |
e04a16fb | 1464 | tree code; |
d7afe286 | 1465 | tree class_decl; |
e04a16fb AG |
1466 | #define ACC_TRANSLATED 0x4000 |
1467 | int accflags = get_access_flags_from_decl (mdecl) | ACC_TRANSLATED; | |
af434fa7 | 1468 | |
d7afe286 BM |
1469 | class_decl = DECL_CONTEXT (mdecl); |
1470 | /* For interfaces, the index field contains the dispatch index. */ | |
1471 | if (CLASS_INTERFACE (TYPE_NAME (class_decl))) | |
4a90aeeb | 1472 | index = build_int_cst (NULL_TREE, |
7d60be94 | 1473 | get_interface_method_index (mdecl, class_decl)); |
af434fa7 AH |
1474 | else if (!flag_indirect_dispatch && get_method_index (mdecl) != NULL_TREE) |
1475 | index = get_method_index (mdecl); | |
861ef928 BM |
1476 | else |
1477 | index = integer_minus_one_node; | |
1478 | ||
e04a16fb | 1479 | code = null_pointer_node; |
fbb4c46b TT |
1480 | if (METHOD_ABSTRACT (mdecl)) |
1481 | code = build1 (ADDR_EXPR, nativecode_ptr_type_node, | |
1482 | soft_abstractmethod_node); | |
1483 | else | |
65e9700c BM |
1484 | code = build1 (ADDR_EXPR, nativecode_ptr_type_node, |
1485 | make_local_function_alias (mdecl)); | |
e04a16fb AG |
1486 | START_RECORD_CONSTRUCTOR (minit, method_type_node); |
1487 | PUSH_FIELD_VALUE (minit, "name", | |
1488 | build_utf8_ref (DECL_CONSTRUCTOR_P (mdecl) ? | |
1489 | init_identifier_node | |
1490 | : DECL_NAME (mdecl))); | |
7e57923c AH |
1491 | { |
1492 | tree signature = build_java_signature (TREE_TYPE (mdecl)); | |
1493 | PUSH_FIELD_VALUE (minit, "signature", | |
1494 | (build_utf8_ref | |
1495 | (unmangle_classname | |
1496 | (IDENTIFIER_POINTER(signature), | |
1497 | IDENTIFIER_LENGTH(signature))))); | |
1498 | } | |
7d60be94 | 1499 | PUSH_FIELD_VALUE (minit, "accflags", build_int_cst (NULL_TREE, accflags)); |
861ef928 | 1500 | PUSH_FIELD_VALUE (minit, "index", index); |
e04a16fb | 1501 | PUSH_FIELD_VALUE (minit, "ncode", code); |
66b461ce TT |
1502 | |
1503 | { | |
1504 | /* Compute the `throws' information for the method. */ | |
a3bcfa67 | 1505 | tree table = null_pointer_node; |
66b461ce TT |
1506 | if (DECL_FUNCTION_THROWS (mdecl) != NULL_TREE) |
1507 | { | |
1508 | int length = 1 + list_length (DECL_FUNCTION_THROWS (mdecl)); | |
1509 | tree iter, type, array; | |
1510 | char buf[60]; | |
1511 | ||
1512 | table = tree_cons (NULL_TREE, table, NULL_TREE); | |
1513 | for (iter = DECL_FUNCTION_THROWS (mdecl); | |
1514 | iter != NULL_TREE; | |
1515 | iter = TREE_CHAIN (iter)) | |
1516 | { | |
21140beb | 1517 | tree sig = DECL_NAME (TYPE_NAME (TREE_VALUE (iter))); |
66b461ce TT |
1518 | tree utf8 |
1519 | = build_utf8_ref (unmangle_classname (IDENTIFIER_POINTER (sig), | |
1520 | IDENTIFIER_LENGTH (sig))); | |
1521 | table = tree_cons (NULL_TREE, utf8, table); | |
1522 | } | |
1523 | type = build_prim_array_type (ptr_type_node, length); | |
4038c495 | 1524 | table = build_constructor_from_list (type, table); |
66b461ce TT |
1525 | /* Compute something unique enough. */ |
1526 | sprintf (buf, "_methods%d", method_name_count++); | |
1527 | array = build_decl (VAR_DECL, get_identifier (buf), type); | |
1528 | DECL_INITIAL (array) = table; | |
1529 | TREE_STATIC (array) = 1; | |
1530 | DECL_ARTIFICIAL (array) = 1; | |
1531 | DECL_IGNORED_P (array) = 1; | |
0e6df31e | 1532 | rest_of_decl_compilation (array, 1, 0); |
66b461ce TT |
1533 | |
1534 | table = build1 (ADDR_EXPR, ptr_type_node, array); | |
1535 | } | |
1536 | ||
1537 | PUSH_FIELD_VALUE (minit, "throws", table); | |
1538 | } | |
1539 | ||
e04a16fb AG |
1540 | FINISH_RECORD_CONSTRUCTOR (minit); |
1541 | return minit; | |
1542 | } | |
1543 | ||
4bcde32e | 1544 | static tree |
0a2f0c54 | 1545 | get_dispatch_vector (tree type) |
e04a16fb AG |
1546 | { |
1547 | tree vtable = TYPE_VTABLE (type); | |
5c64ead4 TT |
1548 | |
1549 | if (vtable == NULL_TREE) | |
e04a16fb | 1550 | { |
665f2503 | 1551 | HOST_WIDE_INT i; |
e04a16fb AG |
1552 | tree method; |
1553 | tree super = CLASSTYPE_SUPER (type); | |
665f2503 | 1554 | HOST_WIDE_INT nvirtuals = tree_low_cst (TYPE_NVIRTUALS (type), 0); |
e04a16fb AG |
1555 | vtable = make_tree_vec (nvirtuals); |
1556 | TYPE_VTABLE (type) = vtable; | |
1557 | if (super != NULL_TREE) | |
1558 | { | |
1559 | tree super_vtable = get_dispatch_vector (super); | |
665f2503 RK |
1560 | |
1561 | for (i = tree_low_cst (TYPE_NVIRTUALS (super), 0); --i >= 0; ) | |
e04a16fb AG |
1562 | TREE_VEC_ELT (vtable, i) = TREE_VEC_ELT (super_vtable, i); |
1563 | } | |
665f2503 | 1564 | |
e04a16fb AG |
1565 | for (method = TYPE_METHODS (type); method != NULL_TREE; |
1566 | method = TREE_CHAIN (method)) | |
af434fa7 AH |
1567 | { |
1568 | tree method_index = get_method_index (method); | |
1569 | if (method_index != NULL_TREE | |
1570 | && host_integerp (method_index, 0)) | |
1571 | TREE_VEC_ELT (vtable, tree_low_cst (method_index, 0)) = method; | |
1572 | } | |
e04a16fb | 1573 | } |
665f2503 | 1574 | |
e04a16fb AG |
1575 | return vtable; |
1576 | } | |
1577 | ||
4bcde32e | 1578 | static tree |
0a2f0c54 | 1579 | get_dispatch_table (tree type, tree this_class_addr) |
e04a16fb | 1580 | { |
13107ec0 | 1581 | int abstract_p = CLASS_ABSTRACT (TYPE_NAME (type)); |
e04a16fb | 1582 | tree vtable = get_dispatch_vector (type); |
67231816 | 1583 | int i, j; |
e04a16fb AG |
1584 | tree list = NULL_TREE; |
1585 | int nvirtuals = TREE_VEC_LENGTH (vtable); | |
67231816 | 1586 | int arraysize; |
eec87542 | 1587 | tree gc_descr; |
67231816 | 1588 | |
e04a16fb AG |
1589 | for (i = nvirtuals; --i >= 0; ) |
1590 | { | |
1591 | tree method = TREE_VEC_ELT (vtable, i); | |
1592 | if (METHOD_ABSTRACT (method)) | |
13107ec0 TT |
1593 | { |
1594 | if (! abstract_p) | |
d4ee4d25 | 1595 | warning (0, "%Jabstract method in non-abstract class", method); |
67231816 RH |
1596 | |
1597 | if (TARGET_VTABLE_USES_DESCRIPTORS) | |
1598 | for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j) | |
1599 | list = tree_cons (NULL_TREE, null_pointer_node, list); | |
1600 | else | |
1601 | list = tree_cons (NULL_TREE, null_pointer_node, list); | |
13107ec0 TT |
1602 | } |
1603 | else | |
1604 | { | |
67231816 RH |
1605 | if (TARGET_VTABLE_USES_DESCRIPTORS) |
1606 | for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j) | |
1607 | { | |
94cdeb1a | 1608 | tree fdesc = build2 (FDESC_EXPR, nativecode_ptr_type_node, |
7d60be94 | 1609 | method, build_int_cst (NULL_TREE, j)); |
67231816 RH |
1610 | TREE_CONSTANT (fdesc) = 1; |
1611 | list = tree_cons (NULL_TREE, fdesc, list); | |
1612 | } | |
1613 | else | |
1614 | list = tree_cons (NULL_TREE, | |
1615 | build1 (ADDR_EXPR, nativecode_ptr_type_node, | |
1616 | method), | |
1617 | list); | |
13107ec0 | 1618 | } |
e04a16fb | 1619 | } |
67231816 | 1620 | |
5830574a TT |
1621 | /* Dummy entry for compatibility with G++ -fvtable-thunks. When |
1622 | using the Boehm GC we sometimes stash a GC type descriptor | |
8f975c18 APB |
1623 | there. We set the PURPOSE to NULL_TREE not to interfere (reset) |
1624 | the emitted byte count during the output to the assembly file. */ | |
eec87542 HB |
1625 | /* With TARGET_VTABLE_USES_DESCRIPTORS, we only add one extra |
1626 | fake "function descriptor". It's first word is the is the class | |
1627 | pointer, and subsequent words (usually one) contain the GC descriptor. | |
1628 | In all other cases, we reserve two extra vtable slots. */ | |
1629 | gc_descr = get_boehm_type_descriptor (type); | |
1630 | list = tree_cons (NULL_TREE, gc_descr, list); | |
1631 | for (j = 1; j < TARGET_VTABLE_USES_DESCRIPTORS-1; ++j) | |
1632 | list = tree_cons (NULL_TREE, gc_descr, list); | |
dcb36804 PB |
1633 | list = tree_cons (NULL_TREE, this_class_addr, list); |
1634 | ||
1635 | /** Pointer to type_info object (to be implemented), according to g++ ABI. */ | |
1636 | list = tree_cons (NULL_TREE, null_pointer_node, list); | |
1637 | /** Offset to start of whole object. Always (ptrdiff_t)0 for Java. */ | |
1638 | list = tree_cons (integer_zero_node, null_pointer_node, list); | |
67231816 | 1639 | |
eec87542 | 1640 | arraysize = (TARGET_VTABLE_USES_DESCRIPTORS? nvirtuals + 1 : nvirtuals + 2); |
67231816 RH |
1641 | if (TARGET_VTABLE_USES_DESCRIPTORS) |
1642 | arraysize *= TARGET_VTABLE_USES_DESCRIPTORS; | |
dcb36804 | 1643 | arraysize += 2; |
4038c495 GB |
1644 | return build_constructor_from_list |
1645 | (build_prim_array_type (nativecode_ptr_type_node, | |
1646 | arraysize), list); | |
e04a16fb AG |
1647 | } |
1648 | ||
af434fa7 AH |
1649 | |
1650 | /* Set the method_index for a method decl. */ | |
1651 | void | |
1652 | set_method_index (tree decl, tree method_index) | |
1653 | { | |
7235c300 AH |
1654 | if (method_index != NULL_TREE) |
1655 | { | |
1656 | /* method_index is null if we're using indirect dispatch. */ | |
1657 | method_index = fold (convert (sizetype, method_index)); | |
af434fa7 | 1658 | |
7235c300 AH |
1659 | if (TARGET_VTABLE_USES_DESCRIPTORS) |
1660 | /* Add one to skip bogus descriptor for class and GC descriptor. */ | |
1661 | method_index = size_binop (PLUS_EXPR, method_index, size_int (1)); | |
1662 | else | |
1663 | /* Add 1 to skip "class" field of dtable, and 1 to skip GC | |
1664 | descriptor. */ | |
1665 | method_index = size_binop (PLUS_EXPR, method_index, size_int (2)); | |
1666 | } | |
af434fa7 AH |
1667 | |
1668 | DECL_VINDEX (decl) = method_index; | |
1669 | } | |
1670 | ||
1671 | /* Get the method_index for a method decl. */ | |
1672 | tree | |
1673 | get_method_index (tree decl) | |
1674 | { | |
1675 | tree method_index = DECL_VINDEX (decl); | |
1676 | ||
1677 | if (! method_index) | |
1678 | return NULL; | |
1679 | ||
1680 | if (TARGET_VTABLE_USES_DESCRIPTORS) | |
1681 | /* Sub one to skip bogus descriptor for class and GC descriptor. */ | |
1682 | method_index = size_binop (MINUS_EXPR, method_index, size_int (1)); | |
1683 | else | |
1684 | /* Sub 1 to skip "class" field of dtable, and 1 to skip GC descriptor. */ | |
1685 | method_index = size_binop (MINUS_EXPR, method_index, size_int (2)); | |
1686 | ||
1687 | return method_index; | |
1688 | } | |
1689 | ||
5c64ead4 TT |
1690 | static int |
1691 | supers_all_compiled (tree type) | |
1692 | { | |
1693 | while (type != NULL_TREE) | |
1694 | { | |
1695 | if (!assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))))) | |
1696 | return 0; | |
1697 | type = CLASSTYPE_SUPER (type); | |
1698 | } | |
1699 | return 1; | |
1700 | } | |
1701 | ||
e04a16fb | 1702 | void |
0a2f0c54 | 1703 | make_class_data (tree type) |
e04a16fb AG |
1704 | { |
1705 | tree decl, cons, temp; | |
1706 | tree field, fields_decl; | |
1707 | tree static_fields = NULL_TREE; | |
1708 | tree instance_fields = NULL_TREE; | |
1709 | HOST_WIDE_INT static_field_count = 0; | |
1710 | HOST_WIDE_INT instance_field_count = 0; | |
1711 | HOST_WIDE_INT field_count; | |
1712 | tree field_array_type; | |
1713 | tree method; | |
1714 | tree methods = NULL_TREE; | |
1715 | tree dtable_decl = NULL_TREE; | |
1716 | HOST_WIDE_INT method_count = 0; | |
1717 | tree method_array_type; | |
1718 | tree methods_decl; | |
1719 | tree super; | |
1720 | tree this_class_addr; | |
1721 | tree constant_pool_constructor; | |
1722 | tree interfaces = null_pointer_node; | |
1723 | int interface_len = 0; | |
dba370a8 | 1724 | int uses_jv_markobj = 0; |
e04a16fb | 1725 | tree type_decl = TYPE_NAME (type); |
dba370a8 DD |
1726 | tree id_main = get_identifier("main"); |
1727 | tree id_class = get_identifier("java.lang.Class"); | |
dcb36804 PB |
1728 | /** Offset from start of virtual function table declaration |
1729 | to where objects actually point at, following new g++ ABI. */ | |
5be014d5 | 1730 | tree dtable_start_offset = size_int (2 * POINTER_SIZE / BITS_PER_UNIT); |
97b8365c TT |
1731 | VEC(int, heap) *field_indexes; |
1732 | tree first_real_field; | |
e04a16fb | 1733 | |
621ae65d | 1734 | this_class_addr = build_static_class_ref (type); |
e04a16fb AG |
1735 | decl = TREE_OPERAND (this_class_addr, 0); |
1736 | ||
dba370a8 DD |
1737 | if (supers_all_compiled (type) && ! CLASS_INTERFACE (type_decl) |
1738 | && !flag_indirect_dispatch) | |
1739 | { | |
1740 | tree dtable = get_dispatch_table (type, this_class_addr); | |
b1138221 | 1741 | uses_jv_markobj = uses_jv_markobj_p (dtable); |
97b8365c TT |
1742 | if (type == class_type_node && class_dtable_decl != NULL_TREE) |
1743 | { | |
1744 | /* We've already created some other class, and consequently | |
1745 | we made class_dtable_decl. Now we just want to fill it | |
1746 | in. */ | |
1747 | dtable_decl = class_dtable_decl; | |
1748 | } | |
1749 | else | |
1750 | { | |
1751 | dtable_decl = build_dtable_decl (type); | |
1752 | TREE_STATIC (dtable_decl) = 1; | |
1753 | DECL_ARTIFICIAL (dtable_decl) = 1; | |
1754 | DECL_IGNORED_P (dtable_decl) = 1; | |
1755 | } | |
1756 | ||
dba370a8 | 1757 | TREE_PUBLIC (dtable_decl) = 1; |
97b8365c | 1758 | DECL_INITIAL (dtable_decl) = dtable; |
696fbee7 AH |
1759 | /* The only dispatch table exported from a DSO is the dispatch |
1760 | table for java.lang.Class. */ | |
1761 | if (DECL_NAME (type_decl) != id_class) | |
3e603aef | 1762 | java_hide_decl (dtable_decl); |
621ae65d AH |
1763 | if (! flag_indirect_classes) |
1764 | rest_of_decl_compilation (dtable_decl, 1, 0); | |
97b8365c TT |
1765 | /* Maybe we're compiling Class as the first class. If so, set |
1766 | class_dtable_decl to the decl we just made. */ | |
1767 | if (type == class_type_node && class_dtable_decl == NULL_TREE) | |
dba370a8 DD |
1768 | class_dtable_decl = dtable_decl; |
1769 | } | |
1770 | ||
e04a16fb AG |
1771 | /* Build Field array. */ |
1772 | field = TYPE_FIELDS (type); | |
36739040 TT |
1773 | while (field && DECL_ARTIFICIAL (field)) |
1774 | field = TREE_CHAIN (field); /* Skip dummy fields. */ | |
1775 | if (field && DECL_NAME (field) == NULL_TREE) | |
e04a16fb | 1776 | field = TREE_CHAIN (field); /* Skip dummy field for inherited data. */ |
97b8365c TT |
1777 | first_real_field = field; |
1778 | ||
1779 | /* First count static and instance fields. */ | |
1780 | for ( ; field != NULL_TREE; field = TREE_CHAIN (field)) | |
1781 | { | |
1782 | if (! DECL_ARTIFICIAL (field)) | |
1783 | { | |
1784 | if (FIELD_STATIC (field)) | |
1785 | static_field_count++; | |
1786 | else if (uses_jv_markobj || !flag_reduced_reflection) | |
1787 | instance_field_count++; | |
1788 | } | |
1789 | } | |
1790 | field_count = static_field_count + instance_field_count; | |
1791 | field_indexes = VEC_alloc (int, heap, field_count); | |
1792 | ||
1793 | /* gcj sorts fields so that static fields come first, followed by | |
1794 | instance fields. Unfortunately, by the time this takes place we | |
1795 | have already generated the reflection_data for this class, and | |
61a89891 | 1796 | that data contains indexes into the fields. So, we generate a |
97b8365c TT |
1797 | permutation that maps each original field index to its final |
1798 | position. Then we pass this permutation to | |
1799 | rewrite_reflection_indexes(), which fixes up the reflection | |
1800 | data. */ | |
1801 | { | |
1802 | int i; | |
1803 | int static_count = 0; | |
1804 | int instance_count = static_field_count; | |
1805 | int field_index; | |
1806 | ||
1807 | for (i = 0, field = first_real_field; | |
1808 | field != NULL_TREE; | |
1809 | field = TREE_CHAIN (field), i++) | |
1810 | { | |
1811 | if (! DECL_ARTIFICIAL (field)) | |
1812 | { | |
1813 | field_index = 0; | |
1814 | if (FIELD_STATIC (field)) | |
1815 | field_index = static_count++; | |
1816 | else if (uses_jv_markobj || !flag_reduced_reflection) | |
1817 | field_index = instance_count++; | |
1818 | VEC_quick_push (int, field_indexes, field_index); | |
1819 | } | |
1820 | } | |
1821 | } | |
1822 | ||
1823 | for (field = first_real_field; field != NULL_TREE; | |
1824 | field = TREE_CHAIN (field)) | |
e04a16fb AG |
1825 | { |
1826 | if (! DECL_ARTIFICIAL (field)) | |
1827 | { | |
e04a16fb AG |
1828 | if (FIELD_STATIC (field)) |
1829 | { | |
dba370a8 DD |
1830 | /* We must always create reflection data for static fields |
1831 | as it is used in the creation of the field itself. */ | |
1832 | tree init = make_field_value (field); | |
cd9643f7 | 1833 | tree initial = DECL_INITIAL (field); |
e04a16fb | 1834 | static_fields = tree_cons (NULL_TREE, init, static_fields); |
cd9643f7 PB |
1835 | /* If the initial value is a string constant, |
1836 | prevent output_constant from trying to assemble the value. */ | |
1837 | if (initial != NULL_TREE | |
1838 | && TREE_TYPE (initial) == string_ptr_type_node) | |
1839 | DECL_INITIAL (field) = NULL_TREE; | |
0e6df31e | 1840 | rest_of_decl_compilation (field, 1, 1); |
cd9643f7 | 1841 | DECL_INITIAL (field) = initial; |
e04a16fb | 1842 | } |
dba370a8 | 1843 | else if (uses_jv_markobj || !flag_reduced_reflection) |
e04a16fb | 1844 | { |
dba370a8 | 1845 | tree init = make_field_value (field); |
e04a16fb AG |
1846 | instance_fields = tree_cons (NULL_TREE, init, instance_fields); |
1847 | } | |
1848 | } | |
1849 | } | |
97b8365c | 1850 | |
e04a16fb AG |
1851 | if (field_count > 0) |
1852 | { | |
1853 | static_fields = nreverse (static_fields); | |
1854 | instance_fields = nreverse (instance_fields); | |
1855 | static_fields = chainon (static_fields, instance_fields); | |
1856 | field_array_type = build_prim_array_type (field_type_node, field_count); | |
1857 | fields_decl = build_decl (VAR_DECL, mangled_classname ("_FL_", type), | |
1858 | field_array_type); | |
4038c495 GB |
1859 | DECL_INITIAL (fields_decl) = build_constructor_from_list |
1860 | (field_array_type, static_fields); | |
e04a16fb AG |
1861 | TREE_STATIC (fields_decl) = 1; |
1862 | DECL_ARTIFICIAL (fields_decl) = 1; | |
1863 | DECL_IGNORED_P (fields_decl) = 1; | |
0e6df31e | 1864 | rest_of_decl_compilation (fields_decl, 1, 0); |
e04a16fb AG |
1865 | } |
1866 | else | |
1867 | fields_decl = NULL_TREE; | |
1868 | ||
1869 | /* Build Method array. */ | |
c02ebb18 | 1870 | for (method = TYPE_METHODS (type); |
e04a16fb AG |
1871 | method != NULL_TREE; method = TREE_CHAIN (method)) |
1872 | { | |
75d01ad7 PB |
1873 | tree init; |
1874 | if (METHOD_PRIVATE (method) | |
cf69bfbf | 1875 | && ! flag_keep_inline_functions |
39afeb1a | 1876 | && optimize) |
75d01ad7 | 1877 | continue; |
0b1214ef | 1878 | /* Even if we have a decl, we don't necessarily have the code. |
36739040 TT |
1879 | This can happen if we inherit a method from a superclass for |
1880 | which we don't have a .class file. */ | |
1881 | if (METHOD_DUMMY (method)) | |
1882 | continue; | |
dba370a8 DD |
1883 | |
1884 | /* Generate method reflection data if: | |
1885 | ||
1886 | - !flag_reduced_reflection. | |
1887 | ||
1888 | - <clinit> -- The runtime uses reflection to initialize the | |
1889 | class. | |
1890 | ||
1891 | - Any method in class java.lang.Class -- Class.forName() and | |
1892 | perhaps other things require it. | |
1893 | ||
1894 | - class$ -- It does not work if reflection data missing. | |
1895 | ||
1896 | - main -- Reflection is used to find main(String[]) methods. | |
1897 | ||
1898 | - public not static -- It is potentially part of an | |
1899 | interface. The runtime uses reflection data to build | |
1900 | interface dispatch tables. */ | |
1901 | if (!flag_reduced_reflection | |
1902 | || DECL_CLINIT_P (method) | |
1903 | || DECL_NAME (type_decl) == id_class | |
1904 | || DECL_NAME (method) == id_main | |
279e32c9 | 1905 | || (METHOD_PUBLIC (method) && !METHOD_STATIC (method))) |
dba370a8 DD |
1906 | { |
1907 | init = make_method_value (method); | |
1908 | method_count++; | |
1909 | methods = tree_cons (NULL_TREE, init, methods); | |
1910 | } | |
e04a16fb AG |
1911 | } |
1912 | method_array_type = build_prim_array_type (method_type_node, method_count); | |
1913 | methods_decl = build_decl (VAR_DECL, mangled_classname ("_MT_", type), | |
1914 | method_array_type); | |
4038c495 GB |
1915 | DECL_INITIAL (methods_decl) = build_constructor_from_list |
1916 | (method_array_type, nreverse (methods)); | |
e04a16fb AG |
1917 | TREE_STATIC (methods_decl) = 1; |
1918 | DECL_ARTIFICIAL (methods_decl) = 1; | |
1919 | DECL_IGNORED_P (methods_decl) = 1; | |
0e6df31e | 1920 | rest_of_decl_compilation (methods_decl, 1, 0); |
e04a16fb | 1921 | |
6d37cf2f PB |
1922 | if (class_dtable_decl == NULL_TREE) |
1923 | { | |
1924 | class_dtable_decl = build_dtable_decl (class_type_node); | |
1925 | TREE_STATIC (class_dtable_decl) = 1; | |
1926 | DECL_ARTIFICIAL (class_dtable_decl) = 1; | |
1927 | DECL_IGNORED_P (class_dtable_decl) = 1; | |
69ca5554 | 1928 | if (is_compiled_class (class_type_node) != 2) |
97b8365c TT |
1929 | { |
1930 | DECL_EXTERNAL (class_dtable_decl) = 1; | |
1931 | rest_of_decl_compilation (class_dtable_decl, 1, 0); | |
1932 | } | |
e04a16fb AG |
1933 | } |
1934 | ||
1935 | super = CLASSTYPE_SUPER (type); | |
1936 | if (super == NULL_TREE) | |
1937 | super = null_pointer_node; | |
36739040 TT |
1938 | else if (! flag_indirect_dispatch |
1939 | && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl))) | |
d9bbf3f7 | 1940 | && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (super))))) |
e04a16fb AG |
1941 | super = build_class_ref (super); |
1942 | else | |
1943 | { | |
1944 | int super_index = alloc_class_constant (super); | |
7d60be94 | 1945 | super = build_int_cst (ptr_type_node, super_index); |
e04a16fb AG |
1946 | } |
1947 | ||
1948 | /* Build and emit the array of implemented interfaces. */ | |
1949 | if (type != object_type_node) | |
604a3205 NS |
1950 | interface_len = BINFO_N_BASE_BINFOS (TYPE_BINFO (type)) - 1; |
1951 | ||
e04a16fb AG |
1952 | if (interface_len > 0) |
1953 | { | |
1954 | tree init = NULL_TREE; | |
1955 | int i; | |
1956 | tree interface_array_type, idecl; | |
1957 | interface_array_type | |
1958 | = build_prim_array_type (class_ptr_type, interface_len); | |
1959 | idecl = build_decl (VAR_DECL, mangled_classname ("_IF_", type), | |
1960 | interface_array_type); | |
fa743e8c | 1961 | |
e04a16fb AG |
1962 | for (i = interface_len; i > 0; i--) |
1963 | { | |
fa743e8c | 1964 | tree child = BINFO_BASE_BINFO (TYPE_BINFO (type), i); |
e04a16fb AG |
1965 | tree iclass = BINFO_TYPE (child); |
1966 | tree index; | |
85194ee9 AH |
1967 | if (! flag_indirect_dispatch |
1968 | && (assume_compiled | |
1969 | (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (iclass)))))) | |
e04a16fb AG |
1970 | index = build_class_ref (iclass); |
1971 | else | |
1972 | { | |
85194ee9 | 1973 | int int_index = alloc_class_constant (iclass); |
7d60be94 | 1974 | index = build_int_cst (ptr_type_node, int_index); |
e04a16fb AG |
1975 | } |
1976 | init = tree_cons (NULL_TREE, index, init); | |
1977 | } | |
4038c495 GB |
1978 | DECL_INITIAL (idecl) = build_constructor_from_list (interface_array_type, |
1979 | init); | |
e04a16fb AG |
1980 | TREE_STATIC (idecl) = 1; |
1981 | DECL_ARTIFICIAL (idecl) = 1; | |
1982 | DECL_IGNORED_P (idecl) = 1; | |
1983 | interfaces = build1 (ADDR_EXPR, ptr_type_node, idecl); | |
0e6df31e | 1984 | rest_of_decl_compilation (idecl, 1, 0); |
e04a16fb AG |
1985 | } |
1986 | ||
1987 | constant_pool_constructor = build_constants_constructor (); | |
1988 | ||
85194ee9 AH |
1989 | if (flag_indirect_dispatch) |
1990 | { | |
1991 | TYPE_OTABLE_DECL (type) | |
1992 | = emit_symbol_table | |
1993 | (DECL_NAME (TYPE_OTABLE_DECL (type)), | |
1994 | TYPE_OTABLE_DECL (type), TYPE_OTABLE_METHODS (type), | |
36739040 | 1995 | TYPE_OTABLE_SYMS_DECL (type), integer_type_node, 1); |
85194ee9 AH |
1996 | |
1997 | TYPE_ATABLE_DECL (type) | |
1998 | = emit_symbol_table | |
1999 | (DECL_NAME (TYPE_ATABLE_DECL (type)), | |
2000 | TYPE_ATABLE_DECL (type), TYPE_ATABLE_METHODS (type), | |
36739040 TT |
2001 | TYPE_ATABLE_SYMS_DECL (type), ptr_type_node, 1); |
2002 | ||
2003 | TYPE_ITABLE_DECL (type) | |
2004 | = emit_symbol_table | |
2005 | (DECL_NAME (TYPE_ITABLE_DECL (type)), | |
2006 | TYPE_ITABLE_DECL (type), TYPE_ITABLE_METHODS (type), | |
2007 | TYPE_ITABLE_SYMS_DECL (type), ptr_type_node, 2); | |
85194ee9 AH |
2008 | } |
2009 | ||
2010 | TYPE_CTABLE_DECL (type) = emit_catch_table (type); | |
2011 | ||
e04a16fb | 2012 | START_RECORD_CONSTRUCTOR (temp, object_type_node); |
78857b4e | 2013 | PUSH_FIELD_VALUE (temp, "vtable", |
e046c56e AH |
2014 | (flag_indirect_classes |
2015 | ? null_pointer_node | |
5be014d5 | 2016 | : build2 (POINTER_PLUS_EXPR, dtable_ptr_type, |
e046c56e AH |
2017 | build1 (ADDR_EXPR, dtable_ptr_type, |
2018 | class_dtable_decl), | |
2019 | dtable_start_offset))); | |
64aa33dd TT |
2020 | if (! flag_hash_synchronization) |
2021 | PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node); | |
e04a16fb AG |
2022 | FINISH_RECORD_CONSTRUCTOR (temp); |
2023 | START_RECORD_CONSTRUCTOR (cons, class_type_node); | |
2024 | PUSH_SUPER_VALUE (cons, temp); | |
2a4d0626 | 2025 | PUSH_FIELD_VALUE (cons, "next_or_version", gcj_abi_version); |
75d01ad7 | 2026 | PUSH_FIELD_VALUE (cons, "name", build_utf8_ref (DECL_NAME (type_decl))); |
e04a16fb | 2027 | PUSH_FIELD_VALUE (cons, "accflags", |
4a90aeeb | 2028 | build_int_cst (NULL_TREE, |
7d60be94 | 2029 | get_access_flags_from_decl (type_decl))); |
e04a16fb | 2030 | |
93089423 AH |
2031 | PUSH_FIELD_VALUE (cons, "superclass", |
2032 | CLASS_INTERFACE (type_decl) ? null_pointer_node : super); | |
e04a16fb AG |
2033 | PUSH_FIELD_VALUE (cons, "constants", constant_pool_constructor); |
2034 | PUSH_FIELD_VALUE (cons, "methods", | |
dba370a8 DD |
2035 | methods_decl == NULL_TREE ? null_pointer_node |
2036 | : build1 (ADDR_EXPR, method_ptr_type_node, methods_decl)); | |
4a90aeeb | 2037 | PUSH_FIELD_VALUE (cons, "method_count", |
7d60be94 | 2038 | build_int_cst (NULL_TREE, method_count)); |
861ef928 BM |
2039 | |
2040 | if (flag_indirect_dispatch) | |
90471585 | 2041 | PUSH_FIELD_VALUE (cons, "vtable_method_count", integer_minus_one_node); |
861ef928 BM |
2042 | else |
2043 | PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type)); | |
2044 | ||
e04a16fb AG |
2045 | PUSH_FIELD_VALUE (cons, "fields", |
2046 | fields_decl == NULL_TREE ? null_pointer_node | |
2047 | : build1 (ADDR_EXPR, field_ptr_type_node, fields_decl)); | |
36739040 TT |
2048 | /* If we're using the binary compatibility ABI we don't know the |
2049 | size until load time. */ | |
2050 | PUSH_FIELD_VALUE (cons, "size_in_bytes", | |
2051 | (flag_indirect_dispatch | |
2052 | ? integer_minus_one_node | |
2053 | : size_in_bytes (type))); | |
2054 | PUSH_FIELD_VALUE (cons, "field_count", | |
7d60be94 | 2055 | build_int_cst (NULL_TREE, field_count)); |
571d54d5 | 2056 | PUSH_FIELD_VALUE (cons, "static_field_count", |
7d60be94 | 2057 | build_int_cst (NULL_TREE, static_field_count)); |
861ef928 BM |
2058 | |
2059 | if (flag_indirect_dispatch) | |
90471585 | 2060 | PUSH_FIELD_VALUE (cons, "vtable", null_pointer_node); |
861ef928 BM |
2061 | else |
2062 | PUSH_FIELD_VALUE (cons, "vtable", | |
2063 | dtable_decl == NULL_TREE ? null_pointer_node | |
5be014d5 | 2064 | : build2 (POINTER_PLUS_EXPR, dtable_ptr_type, |
94cdeb1a RS |
2065 | build1 (ADDR_EXPR, dtable_ptr_type, |
2066 | dtable_decl), | |
2067 | dtable_start_offset)); | |
85194ee9 | 2068 | if (TYPE_OTABLE_METHODS (type) == NULL_TREE) |
861ef928 BM |
2069 | { |
2070 | PUSH_FIELD_VALUE (cons, "otable", null_pointer_node); | |
2071 | PUSH_FIELD_VALUE (cons, "otable_syms", null_pointer_node); | |
2072 | } | |
2073 | else | |
2074 | { | |
517f4918 | 2075 | pushdecl_top_level (TYPE_OTABLE_SYMS_DECL (type)); |
861ef928 | 2076 | PUSH_FIELD_VALUE (cons, "otable", |
85194ee9 | 2077 | build1 (ADDR_EXPR, otable_ptr_type, TYPE_OTABLE_DECL (type))); |
861ef928 | 2078 | PUSH_FIELD_VALUE (cons, "otable_syms", |
9dfc2ec2 | 2079 | build1 (ADDR_EXPR, symbols_array_ptr_type, |
85194ee9 AH |
2080 | TYPE_OTABLE_SYMS_DECL (type))); |
2081 | TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1; | |
6de9cd9a | 2082 | } |
85194ee9 | 2083 | if (TYPE_ATABLE_METHODS(type) == NULL_TREE) |
9dfc2ec2 AH |
2084 | { |
2085 | PUSH_FIELD_VALUE (cons, "atable", null_pointer_node); | |
2086 | PUSH_FIELD_VALUE (cons, "atable_syms", null_pointer_node); | |
861ef928 | 2087 | } |
9dfc2ec2 AH |
2088 | else |
2089 | { | |
517f4918 | 2090 | pushdecl_top_level (TYPE_ATABLE_SYMS_DECL (type)); |
9dfc2ec2 | 2091 | PUSH_FIELD_VALUE (cons, "atable", |
85194ee9 | 2092 | build1 (ADDR_EXPR, atable_ptr_type, TYPE_ATABLE_DECL (type))); |
9dfc2ec2 AH |
2093 | PUSH_FIELD_VALUE (cons, "atable_syms", |
2094 | build1 (ADDR_EXPR, symbols_array_ptr_type, | |
85194ee9 AH |
2095 | TYPE_ATABLE_SYMS_DECL (type))); |
2096 | TREE_CONSTANT (TYPE_ATABLE_DECL (type)) = 1; | |
9dfc2ec2 | 2097 | } |
36739040 TT |
2098 | if (TYPE_ITABLE_METHODS(type) == NULL_TREE) |
2099 | { | |
2100 | PUSH_FIELD_VALUE (cons, "itable", null_pointer_node); | |
2101 | PUSH_FIELD_VALUE (cons, "itable_syms", null_pointer_node); | |
2102 | } | |
2103 | else | |
2104 | { | |
517f4918 | 2105 | pushdecl_top_level (TYPE_ITABLE_SYMS_DECL (type)); |
36739040 TT |
2106 | PUSH_FIELD_VALUE (cons, "itable", |
2107 | build1 (ADDR_EXPR, itable_ptr_type, TYPE_ITABLE_DECL (type))); | |
2108 | PUSH_FIELD_VALUE (cons, "itable_syms", | |
2109 | build1 (ADDR_EXPR, symbols_array_ptr_type, | |
2110 | TYPE_ITABLE_SYMS_DECL (type))); | |
2111 | TREE_CONSTANT (TYPE_ITABLE_DECL (type)) = 1; | |
36739040 | 2112 | } |
90471585 AH |
2113 | |
2114 | PUSH_FIELD_VALUE (cons, "catch_classes", | |
85194ee9 | 2115 | build1 (ADDR_EXPR, ptr_type_node, TYPE_CTABLE_DECL (type))); |
e04a16fb AG |
2116 | PUSH_FIELD_VALUE (cons, "interfaces", interfaces); |
2117 | PUSH_FIELD_VALUE (cons, "loader", null_pointer_node); | |
4a90aeeb | 2118 | PUSH_FIELD_VALUE (cons, "interface_count", |
7d60be94 | 2119 | build_int_cst (NULL_TREE, interface_len)); |
97b51fd0 TT |
2120 | PUSH_FIELD_VALUE (cons, "state", |
2121 | convert (byte_type_node, | |
2122 | build_int_cst (NULL_TREE, JV_STATE_PRELOADING))); | |
e04a16fb | 2123 | |
a7303141 | 2124 | PUSH_FIELD_VALUE (cons, "thread", null_pointer_node); |
173f556c BM |
2125 | PUSH_FIELD_VALUE (cons, "depth", integer_zero_node); |
2126 | PUSH_FIELD_VALUE (cons, "ancestors", null_pointer_node); | |
2127 | PUSH_FIELD_VALUE (cons, "idt", null_pointer_node); | |
5bb11b2e | 2128 | PUSH_FIELD_VALUE (cons, "arrayclass", null_pointer_node); |
28f7d9d0 | 2129 | PUSH_FIELD_VALUE (cons, "protectionDomain", null_pointer_node); |
36739040 TT |
2130 | |
2131 | { | |
2132 | tree assertion_table_ref; | |
2133 | if (TYPE_ASSERTIONS (type) == NULL) | |
2134 | assertion_table_ref = null_pointer_node; | |
2135 | else | |
2136 | assertion_table_ref = build1 (ADDR_EXPR, | |
2137 | build_pointer_type (assertion_table_type), | |
2138 | emit_assertion_table (type)); | |
2139 | ||
2140 | PUSH_FIELD_VALUE (cons, "assertion_table", assertion_table_ref); | |
2141 | } | |
2142 | ||
02972627 | 2143 | PUSH_FIELD_VALUE (cons, "hack_signers", null_pointer_node); |
421f9e60 | 2144 | PUSH_FIELD_VALUE (cons, "chain", null_pointer_node); |
f5310108 | 2145 | PUSH_FIELD_VALUE (cons, "aux_info", null_pointer_node); |
36739040 | 2146 | PUSH_FIELD_VALUE (cons, "engine", null_pointer_node); |
a7303141 | 2147 | |
97b8365c TT |
2148 | if (TYPE_REFLECTION_DATA (current_class)) |
2149 | { | |
2150 | int i; | |
2151 | int count = TYPE_REFLECTION_DATASIZE (current_class); | |
2152 | VEC (constructor_elt, gc) *v | |
2153 | = VEC_alloc (constructor_elt, gc, count); | |
2154 | unsigned char *data = TYPE_REFLECTION_DATA (current_class); | |
2155 | tree max_index = build_int_cst (sizetype, count); | |
2156 | tree index = build_index_type (max_index); | |
2157 | tree type = build_array_type (unsigned_byte_type_node, index); | |
2158 | char buf[64]; | |
2159 | tree array; | |
2160 | static int reflection_data_count; | |
2161 | ||
2162 | sprintf (buf, "_reflection_data_%d", reflection_data_count++); | |
2163 | array = build_decl (VAR_DECL, get_identifier (buf), type); | |
2164 | ||
2165 | rewrite_reflection_indexes (field_indexes); | |
2166 | ||
2167 | for (i = 0; i < count; i++) | |
2168 | { | |
2169 | constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL); | |
2170 | elt->index = build_int_cst (sizetype, i); | |
2171 | elt->value = build_int_cstu (byte_type_node, data[i]); | |
2172 | } | |
2173 | ||
2174 | DECL_INITIAL (array) = build_constructor (type, v); | |
2175 | TREE_STATIC (array) = 1; | |
2176 | DECL_ARTIFICIAL (array) = 1; | |
2177 | DECL_IGNORED_P (array) = 1; | |
2178 | TREE_READONLY (array) = 1; | |
2179 | TREE_CONSTANT (DECL_INITIAL (array)) = 1; | |
2180 | rest_of_decl_compilation (array, 1, 0); | |
2181 | ||
2182 | PUSH_FIELD_VALUE (cons, "reflection_data", build_address_of (array)); | |
2183 | ||
2184 | free (data); | |
2185 | TYPE_REFLECTION_DATA (current_class) = NULL; | |
2186 | } | |
2187 | else | |
2188 | PUSH_FIELD_VALUE (cons, "reflection_data", null_pointer_node); | |
2189 | ||
e04a16fb AG |
2190 | FINISH_RECORD_CONSTRUCTOR (cons); |
2191 | ||
2192 | DECL_INITIAL (decl) = cons; | |
b798d8b6 BM |
2193 | |
2194 | /* Hash synchronization requires at least 64-bit alignment. */ | |
2195 | if (flag_hash_synchronization && POINTER_SIZE < 64) | |
2196 | DECL_ALIGN (decl) = 64; | |
2197 | ||
621ae65d AH |
2198 | if (flag_indirect_classes) |
2199 | { | |
2200 | TREE_READONLY (decl) = 1; | |
2201 | TREE_CONSTANT (DECL_INITIAL (decl)) = 1; | |
2202 | } | |
2203 | ||
0e6df31e | 2204 | rest_of_decl_compilation (decl, 1, 0); |
36739040 | 2205 | |
621ae65d AH |
2206 | { |
2207 | tree classdollar_field = build_classdollar_field (type); | |
2208 | if (!flag_indirect_classes) | |
2209 | DECL_INITIAL (classdollar_field) = build_static_class_ref (type); | |
2210 | rest_of_decl_compilation (classdollar_field, 1, 0); | |
2211 | } | |
2212 | ||
36739040 TT |
2213 | TYPE_OTABLE_DECL (type) = NULL_TREE; |
2214 | TYPE_ATABLE_DECL (type) = NULL_TREE; | |
2215 | TYPE_CTABLE_DECL (type) = NULL_TREE; | |
e04a16fb AG |
2216 | } |
2217 | ||
75d01ad7 | 2218 | void |
0a2f0c54 | 2219 | finish_class (void) |
75d01ad7 | 2220 | { |
85194ee9 AH |
2221 | java_expand_catch_classes (current_class); |
2222 | ||
fcf6eeb6 | 2223 | current_function_decl = NULL_TREE; |
e87047c6 | 2224 | TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (current_class)) = 0; |
75d01ad7 PB |
2225 | make_class_data (current_class); |
2226 | register_class (); | |
0e6df31e | 2227 | rest_of_decl_compilation (TYPE_NAME (current_class), 1, 0); |
75d01ad7 PB |
2228 | } |
2229 | ||
e04a16fb AG |
2230 | /* Return 2 if CLASS is compiled by this compilation job; |
2231 | return 1 if CLASS can otherwise be assumed to be compiled; | |
2232 | return 0 if we cannot assume that CLASS is compiled. | |
2233 | Returns 1 for primitive and 0 for array types. */ | |
2234 | int | |
0a2f0c54 | 2235 | is_compiled_class (tree class) |
e04a16fb | 2236 | { |
b351b287 | 2237 | int seen_in_zip; |
e04a16fb AG |
2238 | if (TREE_CODE (class) == POINTER_TYPE) |
2239 | class = TREE_TYPE (class); | |
2240 | if (TREE_CODE (class) != RECORD_TYPE) /* Primitive types are static. */ | |
2241 | return 1; | |
2242 | if (TYPE_ARRAY_P (class)) | |
2243 | return 0; | |
b351b287 | 2244 | |
b5c4fed9 | 2245 | seen_in_zip = (TYPE_JCF (class) && JCF_SEEN_IN_ZIP (TYPE_JCF (class))); |
97b8365c | 2246 | if (CLASS_FROM_CURRENTLY_COMPILED_P (class)) |
e04a16fb AG |
2247 | { |
2248 | /* The class was seen in the current ZIP file and will be | |
2249 | available as a compiled class in the future but may not have | |
2250 | been loaded already. Load it if necessary. This prevent | |
b351b287 | 2251 | build_class_ref () from crashing. */ |
e04a16fb | 2252 | |
4969f3ea | 2253 | if (seen_in_zip && !CLASS_LOADED_P (class) && (class != current_class)) |
e04a16fb | 2254 | load_class (class, 1); |
b351b287 APB |
2255 | |
2256 | /* We return 2 for class seen in ZIP and class from files | |
2257 | belonging to the same compilation unit */ | |
e04a16fb AG |
2258 | return 2; |
2259 | } | |
2260 | ||
48aedbca | 2261 | if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class))))) |
e04a16fb AG |
2262 | { |
2263 | if (!CLASS_LOADED_P (class)) | |
5e942c50 | 2264 | { |
279e32c9 | 2265 | if (class != current_class) |
5e942c50 APB |
2266 | load_class (class, 1); |
2267 | } | |
e04a16fb AG |
2268 | return 1; |
2269 | } | |
2270 | ||
2271 | return 0; | |
2272 | } | |
2273 | ||
e04a16fb AG |
2274 | /* Build a VAR_DECL for the dispatch table (vtable) for class TYPE. */ |
2275 | ||
2276 | tree | |
0a2f0c54 | 2277 | build_dtable_decl (tree type) |
e04a16fb | 2278 | { |
6de33afa | 2279 | tree dtype, decl; |
8f975c18 APB |
2280 | |
2281 | /* We need to build a new dtable type so that its size is uniquely | |
2282 | computed when we're dealing with the class for real and not just | |
2283 | faking it (like java.lang.Class during the initialization of the | |
dcb36804 | 2284 | compiler.) We know we're not faking a class when CURRENT_CLASS is |
8f975c18 APB |
2285 | TYPE. */ |
2286 | if (current_class == type) | |
2287 | { | |
67231816 RH |
2288 | tree dummy = NULL_TREE; |
2289 | int n; | |
8f975c18 APB |
2290 | |
2291 | dtype = make_node (RECORD_TYPE); | |
67231816 | 2292 | |
dcb36804 PB |
2293 | PUSH_FIELD (dtype, dummy, "top_offset", ptr_type_node); |
2294 | PUSH_FIELD (dtype, dummy, "type_info", ptr_type_node); | |
2295 | ||
8f975c18 | 2296 | PUSH_FIELD (dtype, dummy, "class", class_ptr_type); |
67231816 RH |
2297 | for (n = 1; n < TARGET_VTABLE_USES_DESCRIPTORS; ++n) |
2298 | { | |
2299 | tree tmp_field = build_decl (FIELD_DECL, NULL_TREE, ptr_type_node); | |
2300 | TREE_CHAIN (dummy) = tmp_field; | |
2301 | DECL_CONTEXT (tmp_field) = dtype; | |
2302 | DECL_ARTIFICIAL (tmp_field) = 1; | |
2303 | dummy = tmp_field; | |
2304 | } | |
2305 | ||
2306 | PUSH_FIELD (dtype, dummy, "gc_descr", ptr_type_node); | |
2307 | for (n = 1; n < TARGET_VTABLE_USES_DESCRIPTORS; ++n) | |
2308 | { | |
2309 | tree tmp_field = build_decl (FIELD_DECL, NULL_TREE, ptr_type_node); | |
2310 | TREE_CHAIN (dummy) = tmp_field; | |
2311 | DECL_CONTEXT (tmp_field) = dtype; | |
2312 | DECL_ARTIFICIAL (tmp_field) = 1; | |
2313 | dummy = tmp_field; | |
2314 | } | |
2315 | ||
2316 | n = TREE_VEC_LENGTH (get_dispatch_vector (type)); | |
2317 | if (TARGET_VTABLE_USES_DESCRIPTORS) | |
2318 | n *= TARGET_VTABLE_USES_DESCRIPTORS; | |
2319 | ||
2320 | PUSH_FIELD (dtype, dummy, "methods", | |
2321 | build_prim_array_type (nativecode_ptr_type_node, n)); | |
8f975c18 APB |
2322 | layout_type (dtype); |
2323 | } | |
2324 | else | |
2325 | dtype = dtable_type; | |
2326 | ||
6de33afa RH |
2327 | decl = build_decl (VAR_DECL, get_identifier ("vt$"), dtype); |
2328 | DECL_CONTEXT (decl) = type; | |
2329 | MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); | |
2330 | DECL_VTABLE_P (decl) = 1; | |
2331 | ||
2332 | return decl; | |
e04a16fb AG |
2333 | } |
2334 | ||
2335 | /* Pre-pend the TYPE_FIELDS of THIS_CLASS with a dummy FIELD_DECL for the | |
2336 | fields inherited from SUPER_CLASS. */ | |
2337 | ||
2338 | void | |
0a2f0c54 | 2339 | push_super_field (tree this_class, tree super_class) |
e04a16fb AG |
2340 | { |
2341 | tree base_decl; | |
c2952b01 APB |
2342 | /* Don't insert the field if we're just re-laying the class out. */ |
2343 | if (TYPE_FIELDS (this_class) && !DECL_NAME (TYPE_FIELDS (this_class))) | |
2344 | return; | |
e04a16fb | 2345 | base_decl = build_decl (FIELD_DECL, NULL_TREE, super_class); |
e04a16fb AG |
2346 | DECL_IGNORED_P (base_decl) = 1; |
2347 | TREE_CHAIN (base_decl) = TYPE_FIELDS (this_class); | |
2348 | TYPE_FIELDS (this_class) = base_decl; | |
2349 | DECL_SIZE (base_decl) = TYPE_SIZE (super_class); | |
06ceef4e | 2350 | DECL_SIZE_UNIT (base_decl) = TYPE_SIZE_UNIT (super_class); |
e04a16fb AG |
2351 | } |
2352 | ||
23a79c61 APB |
2353 | /* Handle the different manners we may have to lay out a super class. */ |
2354 | ||
2355 | static tree | |
97b8365c | 2356 | maybe_layout_super_class (tree super_class, tree this_class ATTRIBUTE_UNUSED) |
23a79c61 | 2357 | { |
1b70949a RM |
2358 | if (!super_class) |
2359 | return NULL_TREE; | |
2360 | else if (TREE_CODE (super_class) == RECORD_TYPE) | |
23a79c61 | 2361 | { |
23a79c61 APB |
2362 | if (!CLASS_LOADED_P (super_class)) |
2363 | load_class (super_class, 1); | |
2364 | } | |
2365 | /* We might have to layout the class before its dependency on | |
2366 | the super class gets resolved by java_complete_class */ | |
846b0eb8 | 2367 | else if (TREE_CODE (super_class) == POINTER_TYPE) |
23a79c61 | 2368 | { |
846b0eb8 PB |
2369 | if (TREE_TYPE (super_class) != NULL_TREE) |
2370 | super_class = TREE_TYPE (super_class); | |
2371 | else | |
6ef795d2 | 2372 | gcc_unreachable (); |
23a79c61 APB |
2373 | } |
2374 | if (!TYPE_SIZE (super_class)) | |
2375 | safe_layout_class (super_class); | |
2376 | ||
2377 | return super_class; | |
2378 | } | |
2379 | ||
97b8365c TT |
2380 | /* safe_layout_class just makes sure that we can load a class without |
2381 | disrupting the current_class, input_file, input_line, etc, information | |
2382 | about the class processed currently. */ | |
2383 | ||
2384 | void | |
2385 | safe_layout_class (tree class) | |
2386 | { | |
2387 | tree save_current_class = current_class; | |
2388 | location_t save_location = input_location; | |
2389 | ||
2390 | layout_class (class); | |
2391 | ||
2392 | current_class = save_current_class; | |
2393 | input_location = save_location; | |
2394 | } | |
2395 | ||
e04a16fb | 2396 | void |
0a2f0c54 | 2397 | layout_class (tree this_class) |
e04a16fb | 2398 | { |
279e32c9 | 2399 | int i; |
e04a16fb | 2400 | tree super_class = CLASSTYPE_SUPER (this_class); |
aecf4109 | 2401 | |
b5c4fed9 | 2402 | class_list = tree_cons (this_class, NULL_TREE, class_list); |
c2952b01 APB |
2403 | if (CLASS_BEING_LAIDOUT (this_class)) |
2404 | { | |
2405 | char buffer [1024]; | |
1f8f4a0b | 2406 | char *report; |
c2952b01 | 2407 | tree current; |
aecf4109 | 2408 | |
a1402da3 | 2409 | sprintf (buffer, " with '%s'", |
c2952b01 APB |
2410 | IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)))); |
2411 | obstack_grow (&temporary_obstack, buffer, strlen (buffer)); | |
2412 | ||
b5c4fed9 | 2413 | for (current = TREE_CHAIN (class_list); current; |
c2952b01 APB |
2414 | current = TREE_CHAIN (current)) |
2415 | { | |
2416 | tree decl = TYPE_NAME (TREE_PURPOSE (current)); | |
a1402da3 | 2417 | sprintf (buffer, "\n which inherits from '%s' (%s:%d)", |
c2952b01 | 2418 | IDENTIFIER_POINTER (DECL_NAME (decl)), |
f31686a3 RH |
2419 | DECL_SOURCE_FILE (decl), |
2420 | DECL_SOURCE_LINE (decl)); | |
c2952b01 APB |
2421 | obstack_grow (&temporary_obstack, buffer, strlen (buffer)); |
2422 | } | |
2423 | obstack_1grow (&temporary_obstack, '\0'); | |
1f8f4a0b MM |
2424 | report = obstack_finish (&temporary_obstack); |
2425 | cyclic_inheritance_report = ggc_strdup (report); | |
2426 | obstack_free (&temporary_obstack, report); | |
c2952b01 APB |
2427 | TYPE_SIZE (this_class) = error_mark_node; |
2428 | return; | |
2429 | } | |
2430 | CLASS_BEING_LAIDOUT (this_class) = 1; | |
e04a16fb | 2431 | |
493d561d | 2432 | if (super_class && !CLASS_BEING_LAIDOUT (super_class)) |
e04a16fb | 2433 | { |
7fd9a516 AG |
2434 | tree maybe_super_class |
2435 | = maybe_layout_super_class (super_class, this_class); | |
2436 | if (maybe_super_class == NULL | |
2437 | || TREE_CODE (TYPE_SIZE (maybe_super_class)) == ERROR_MARK) | |
e04a16fb AG |
2438 | { |
2439 | TYPE_SIZE (this_class) = error_mark_node; | |
c2952b01 | 2440 | CLASS_BEING_LAIDOUT (this_class) = 0; |
b5c4fed9 | 2441 | class_list = TREE_CHAIN (class_list); |
e04a16fb AG |
2442 | return; |
2443 | } | |
e04a16fb | 2444 | if (TYPE_SIZE (this_class) == NULL_TREE) |
96c6f628 | 2445 | push_super_field (this_class, maybe_super_class); |
e04a16fb | 2446 | } |
e04a16fb | 2447 | |
e04a16fb | 2448 | layout_type (this_class); |
4832340c | 2449 | |
279e32c9 TT |
2450 | /* Also recursively load/layout any superinterfaces. */ |
2451 | if (TYPE_BINFO (this_class)) | |
c1eacb70 | 2452 | { |
279e32c9 | 2453 | for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (this_class)) - 1; i > 0; i--) |
c1eacb70 | 2454 | { |
279e32c9 TT |
2455 | tree binfo = BINFO_BASE_BINFO (TYPE_BINFO (this_class), i); |
2456 | tree super_interface = BINFO_TYPE (binfo); | |
2457 | tree maybe_super_interface | |
2458 | = maybe_layout_super_class (super_interface, NULL_TREE); | |
2459 | if (maybe_super_interface == NULL | |
2460 | || TREE_CODE (TYPE_SIZE (maybe_super_interface)) == ERROR_MARK) | |
c1eacb70 | 2461 | { |
279e32c9 TT |
2462 | TYPE_SIZE (this_class) = error_mark_node; |
2463 | CLASS_BEING_LAIDOUT (this_class) = 0; | |
2464 | class_list = TREE_CHAIN (class_list); | |
2465 | return; | |
c1eacb70 BM |
2466 | } |
2467 | } | |
2468 | } | |
2469 | ||
aecf4109 TT |
2470 | /* Convert the size back to an SI integer value. */ |
2471 | TYPE_SIZE_UNIT (this_class) = | |
4832340c | 2472 | fold (convert (int_type_node, TYPE_SIZE_UNIT (this_class))); |
c2952b01 APB |
2473 | |
2474 | CLASS_BEING_LAIDOUT (this_class) = 0; | |
b5c4fed9 | 2475 | class_list = TREE_CHAIN (class_list); |
23a79c61 | 2476 | } |
e04a16fb | 2477 | |
aecf4109 TT |
2478 | static void |
2479 | add_miranda_methods (tree base_class, tree search_class) | |
2480 | { | |
fa743e8c | 2481 | int i; |
36739040 TT |
2482 | tree binfo, base_binfo; |
2483 | ||
2484 | if (!CLASS_PARSED_P (search_class)) | |
2485 | load_class (search_class, 1); | |
fa743e8c NS |
2486 | |
2487 | for (binfo = TYPE_BINFO (search_class), i = 1; | |
2488 | BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) | |
aecf4109 TT |
2489 | { |
2490 | tree method_decl; | |
fa743e8c | 2491 | tree elt = BINFO_TYPE (base_binfo); |
aecf4109 | 2492 | |
36739040 TT |
2493 | /* FIXME: This is totally bogus. We should not be handling |
2494 | Miranda methods at all if we're using the BC ABI. */ | |
2495 | if (TYPE_DUMMY (elt)) | |
2496 | continue; | |
2497 | ||
93634679 | 2498 | /* Ensure that interface methods are seen in declared order. */ |
346c5b01 TT |
2499 | if (!CLASS_LOADED_P (elt)) |
2500 | load_class (elt, 1); | |
93634679 BM |
2501 | layout_class_methods (elt); |
2502 | ||
2503 | /* All base classes will have been laid out at this point, so the order | |
2504 | will be correct. This code must match similar layout code in the | |
2505 | runtime. */ | |
aecf4109 TT |
2506 | for (method_decl = TYPE_METHODS (elt); |
2507 | method_decl; method_decl = TREE_CHAIN (method_decl)) | |
2508 | { | |
2509 | tree sig, override; | |
2510 | ||
2511 | /* An interface can have <clinit>. */ | |
2512 | if (ID_CLINIT_P (DECL_NAME (method_decl))) | |
2513 | continue; | |
2514 | ||
2515 | sig = build_java_argument_signature (TREE_TYPE (method_decl)); | |
2516 | override = lookup_argument_method (base_class, | |
2517 | DECL_NAME (method_decl), sig); | |
2518 | if (override == NULL_TREE) | |
2519 | { | |
2520 | /* Found a Miranda method. Add it. */ | |
2521 | tree new_method; | |
2522 | sig = build_java_signature (TREE_TYPE (method_decl)); | |
2523 | new_method | |
2524 | = add_method (base_class, | |
2525 | get_access_flags_from_decl (method_decl), | |
2526 | DECL_NAME (method_decl), sig); | |
2527 | METHOD_INVISIBLE (new_method) = 1; | |
2528 | } | |
2529 | } | |
2530 | ||
2531 | /* Try superinterfaces. */ | |
2532 | add_miranda_methods (base_class, elt); | |
2533 | } | |
2534 | } | |
2535 | ||
23a79c61 | 2536 | void |
0a2f0c54 | 2537 | layout_class_methods (tree this_class) |
23a79c61 APB |
2538 | { |
2539 | tree method_decl, dtable_count; | |
bddefd4f | 2540 | tree super_class, type_name; |
23a79c61 APB |
2541 | |
2542 | if (TYPE_NVIRTUALS (this_class)) | |
2543 | return; | |
b4e18eee | 2544 | |
23a79c61 | 2545 | super_class = CLASSTYPE_SUPER (this_class); |
e04a16fb | 2546 | |
23a79c61 | 2547 | if (super_class) |
e04a16fb | 2548 | { |
846b0eb8 | 2549 | super_class = maybe_layout_super_class (super_class, this_class); |
23a79c61 APB |
2550 | if (!TYPE_NVIRTUALS (super_class)) |
2551 | layout_class_methods (super_class); | |
2552 | dtable_count = TYPE_NVIRTUALS (super_class); | |
2553 | } | |
2554 | else | |
2555 | dtable_count = integer_zero_node; | |
e0a0c416 | 2556 | |
bddefd4f | 2557 | type_name = TYPE_NAME (this_class); |
36739040 TT |
2558 | if (!flag_indirect_dispatch |
2559 | && (CLASS_ABSTRACT (type_name) || CLASS_INTERFACE (type_name))) | |
aecf4109 TT |
2560 | { |
2561 | /* An abstract class can have methods which are declared only in | |
2562 | an implemented interface. These are called "Miranda | |
2563 | methods". We make a dummy method entry for such methods | |
2564 | here. */ | |
2565 | add_miranda_methods (this_class, this_class); | |
2566 | } | |
2567 | ||
c02ebb18 | 2568 | TYPE_METHODS (this_class) = nreverse (TYPE_METHODS (this_class)); |
23a79c61 | 2569 | |
c02ebb18 | 2570 | for (method_decl = TYPE_METHODS (this_class); |
23a79c61 | 2571 | method_decl; method_decl = TREE_CHAIN (method_decl)) |
aecf4109 | 2572 | dtable_count = layout_class_method (this_class, super_class, |
23a79c61 APB |
2573 | method_decl, dtable_count); |
2574 | ||
2575 | TYPE_NVIRTUALS (this_class) = dtable_count; | |
23a79c61 APB |
2576 | } |
2577 | ||
88200a8d TT |
2578 | /* Return the index of METHOD in INTERFACE. This index begins at 1 |
2579 | and is used as an argument for _Jv_LookupInterfaceMethodIdx(). */ | |
d7afe286 BM |
2580 | int |
2581 | get_interface_method_index (tree method, tree interface) | |
2582 | { | |
2583 | tree meth; | |
2584 | int i = 1; | |
2585 | ||
88200a8d | 2586 | for (meth = TYPE_METHODS (interface); ; meth = TREE_CHAIN (meth)) |
d7afe286 BM |
2587 | { |
2588 | if (meth == method) | |
2589 | return i; | |
88200a8d TT |
2590 | /* We don't want to put <clinit> into the interface table. */ |
2591 | if (! ID_CLINIT_P (DECL_NAME (meth))) | |
2592 | ++i; | |
ab184b2a | 2593 | gcc_assert (meth != NULL_TREE); |
d7afe286 BM |
2594 | } |
2595 | } | |
2596 | ||
23a79c61 | 2597 | /* Lay METHOD_DECL out, returning a possibly new value of |
dc08e603 | 2598 | DTABLE_COUNT. Also mangle the method's name. */ |
23a79c61 APB |
2599 | |
2600 | tree | |
0a2f0c54 KG |
2601 | layout_class_method (tree this_class, tree super_class, |
2602 | tree method_decl, tree dtable_count) | |
23a79c61 | 2603 | { |
23a79c61 | 2604 | tree method_name = DECL_NAME (method_decl); |
75d01ad7 | 2605 | |
75d01ad7 | 2606 | TREE_PUBLIC (method_decl) = 1; |
4969f3ea | 2607 | |
696fbee7 AH |
2608 | if (flag_indirect_classes |
2609 | || (METHOD_PRIVATE (method_decl) && METHOD_STATIC (method_decl) | |
2610 | && ! METHOD_NATIVE (method_decl) | |
2611 | && ! special_method_p (method_decl))) | |
3e603aef | 2612 | java_hide_decl (method_decl); |
696fbee7 | 2613 | |
97b8365c | 2614 | /* Considered external unless it is being compiled into this object |
4969f3ea DD |
2615 | file, or it was already flagged as external. */ |
2616 | if (!DECL_EXTERNAL (method_decl)) | |
2617 | DECL_EXTERNAL (method_decl) = ((is_compiled_class (this_class) != 2) | |
2618 | || METHOD_NATIVE (method_decl)); | |
75d01ad7 | 2619 | |
c2952b01 | 2620 | if (ID_INIT_P (method_name)) |
23a79c61 | 2621 | { |
c8e7d2e6 | 2622 | const char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))); |
dc08e603 | 2623 | const char *ptr; |
23a79c61 | 2624 | for (ptr = p; *ptr; ) |
e04a16fb | 2625 | { |
23a79c61 APB |
2626 | if (*ptr++ == '.') |
2627 | p = ptr; | |
2628 | } | |
23a79c61 | 2629 | DECL_CONSTRUCTOR_P (method_decl) = 1; |
97b8365c | 2630 | build_java_signature (TREE_TYPE (method_decl)); |
23a79c61 | 2631 | } |
4a2dd6fe | 2632 | else if (! METHOD_STATIC (method_decl)) |
23a79c61 | 2633 | { |
5c64ead4 | 2634 | tree method_sig = |
97b8365c | 2635 | build_java_signature (TREE_TYPE (method_decl)); |
9c5fdae6 | 2636 | bool method_override = false; |
97b8365c | 2637 | tree super_method = lookup_java_method (super_class, method_name, |
e04a16fb | 2638 | method_sig); |
36739040 | 2639 | if (super_method != NULL_TREE |
3381c28f | 2640 | && ! METHOD_DUMMY (super_method)) |
9c5fdae6 BM |
2641 | { |
2642 | method_override = true; | |
2643 | if (! METHOD_PUBLIC (super_method) && | |
2644 | ! METHOD_PROTECTED (super_method)) | |
2645 | { | |
2646 | /* Don't override private method, or default-access method in | |
2647 | another package. */ | |
2648 | if (METHOD_PRIVATE (super_method) || | |
2649 | ! in_same_package (TYPE_NAME (this_class), | |
2650 | TYPE_NAME (super_class))) | |
2651 | method_override = false; | |
2652 | } | |
2653 | } | |
2654 | if (method_override) | |
23a79c61 | 2655 | { |
af434fa7 AH |
2656 | tree method_index = get_method_index (super_method); |
2657 | set_method_index (method_decl, method_index); | |
2658 | if (method_index == NULL_TREE | |
7235c300 | 2659 | && ! flag_indirect_dispatch |
3381c28f | 2660 | && ! DECL_ARTIFICIAL (super_method)) |
dee15844 JM |
2661 | error ("non-static method %q+D overrides static method", |
2662 | method_decl); | |
23a79c61 | 2663 | } |
36739040 TT |
2664 | else if (this_class == object_type_node |
2665 | && (METHOD_FINAL (method_decl) | |
2666 | || METHOD_PRIVATE (method_decl))) | |
2667 | { | |
2668 | /* We don't generate vtable entries for final Object | |
2669 | methods. This is simply to save space, since every | |
2670 | object would otherwise have to define them. */ | |
2671 | } | |
2672 | else if (! METHOD_PRIVATE (method_decl) | |
23a79c61 APB |
2673 | && dtable_count) |
2674 | { | |
36739040 TT |
2675 | /* We generate vtable entries for final methods because they |
2676 | may one day be changed to non-final. */ | |
af434fa7 | 2677 | set_method_index (method_decl, dtable_count); |
c298ec4e JM |
2678 | dtable_count = fold_build2 (PLUS_EXPR, integer_type_node, |
2679 | dtable_count, integer_one_node); | |
e04a16fb AG |
2680 | } |
2681 | } | |
665f2503 | 2682 | |
23a79c61 | 2683 | return dtable_count; |
e04a16fb AG |
2684 | } |
2685 | ||
8cfb12bf | 2686 | static void |
0a2f0c54 | 2687 | register_class (void) |
e04a16fb | 2688 | { |
8cfb12bf RH |
2689 | tree node; |
2690 | ||
e04a16fb | 2691 | if (!registered_class) |
8cfb12bf | 2692 | registered_class = VEC_alloc (tree, gc, 8); |
e04a16fb | 2693 | |
621ae65d AH |
2694 | if (flag_indirect_classes) |
2695 | node = current_class; | |
2696 | else | |
2697 | node = TREE_OPERAND (build_class_ref (current_class), 0); | |
8cfb12bf | 2698 | VEC_safe_push (tree, gc, registered_class, node); |
e04a16fb AG |
2699 | } |
2700 | ||
e080b30b AH |
2701 | /* Emit a function that calls _Jv_RegisterNewClasses with a list of |
2702 | all the classes we have emitted. */ | |
621ae65d AH |
2703 | |
2704 | static void | |
2705 | emit_indirect_register_classes (tree *list_p) | |
2706 | { | |
2707 | tree klass, t, register_class_fn; | |
2708 | int i; | |
2709 | ||
2710 | tree init = NULL_TREE; | |
2711 | int size = VEC_length (tree, registered_class) * 2 + 1; | |
2712 | tree class_array_type | |
2713 | = build_prim_array_type (ptr_type_node, size); | |
2714 | tree cdecl = build_decl (VAR_DECL, get_identifier ("_Jv_CLS"), | |
2715 | class_array_type); | |
2716 | tree reg_class_list; | |
2717 | for (i = 0; VEC_iterate (tree, registered_class, i, klass); ++i) | |
2718 | { | |
2719 | init = tree_cons (NULL_TREE, | |
2720 | fold_convert (ptr_type_node, | |
2721 | build_static_class_ref (klass)), init); | |
2722 | init = tree_cons | |
2723 | (NULL_TREE, | |
2724 | fold_convert (ptr_type_node, | |
2725 | build_address_of (build_classdollar_field (klass))), | |
2726 | init); | |
2727 | } | |
2728 | init = tree_cons (NULL_TREE, integer_zero_node, init); | |
2729 | DECL_INITIAL (cdecl) = build_constructor_from_list (class_array_type, | |
2730 | nreverse (init)); | |
2731 | TREE_CONSTANT (DECL_INITIAL (cdecl)) = 1; | |
2732 | TREE_STATIC (cdecl) = 1; | |
2733 | DECL_ARTIFICIAL (cdecl) = 1; | |
2734 | DECL_IGNORED_P (cdecl) = 1; | |
2735 | TREE_READONLY (cdecl) = 1; | |
2736 | TREE_CONSTANT (cdecl) = 1; | |
2737 | rest_of_decl_compilation (cdecl, 1, 0); | |
2738 | reg_class_list = fold_convert (ptr_type_node, build_address_of (cdecl)); | |
2739 | ||
2740 | t = build_function_type_list (void_type_node, | |
2741 | build_pointer_type (ptr_type_node), NULL); | |
2742 | t = build_decl (FUNCTION_DECL, | |
2743 | get_identifier ("_Jv_RegisterNewClasses"), t); | |
2744 | TREE_PUBLIC (t) = 1; | |
2745 | DECL_EXTERNAL (t) = 1; | |
2746 | register_class_fn = t; | |
5039610b | 2747 | t = build_call_expr (register_class_fn, 1, reg_class_list); |
621ae65d AH |
2748 | append_to_statement_list (t, list_p); |
2749 | } | |
2750 | ||
2751 | ||
6351543d AG |
2752 | /* Emit something to register classes at start-up time. |
2753 | ||
2754 | The preferred mechanism is through the .jcr section, which contain | |
c9b9aa64 RH |
2755 | a list of pointers to classes which get registered during constructor |
2756 | invocation time. | |
2757 | ||
2758 | The fallback mechanism is to add statements to *LIST_P to call | |
2759 | _Jv_RegisterClass for each class in this file. These statements will | |
2760 | be added to a static constructor function for this translation unit. */ | |
e04a16fb AG |
2761 | |
2762 | void | |
c9b9aa64 | 2763 | emit_register_classes (tree *list_p) |
e04a16fb | 2764 | { |
c9b9aa64 RH |
2765 | if (registered_class == NULL) |
2766 | return; | |
2767 | ||
621ae65d AH |
2768 | if (flag_indirect_classes) |
2769 | { | |
2770 | emit_indirect_register_classes (list_p); | |
2771 | return; | |
2772 | } | |
2773 | ||
e50e6b88 DS |
2774 | /* TARGET_USE_JCR_SECTION defaults to 1 if SUPPORTS_WEAK and |
2775 | TARGET_ASM_NAMED_SECTION, else 0. Some targets meet those conditions | |
2776 | but lack suitable crtbegin/end objects or linker support. These | |
375277f6 | 2777 | targets can override the default in tm.h to use the fallback mechanism. */ |
e50e6b88 | 2778 | if (TARGET_USE_JCR_SECTION) |
6351543d | 2779 | { |
8cfb12bf RH |
2780 | tree klass, t; |
2781 | int i; | |
2782 | ||
ca11a2e9 | 2783 | #ifdef JCR_SECTION_NAME |
d6b5193b | 2784 | switch_to_section (get_section (JCR_SECTION_NAME, SECTION_WRITE, NULL)); |
8cfb12bf RH |
2785 | #else |
2786 | /* A target has defined TARGET_USE_JCR_SECTION, | |
2787 | but doesn't have a JCR_SECTION_NAME. */ | |
2788 | gcc_unreachable (); | |
2789 | #endif | |
715bdd29 | 2790 | assemble_align (POINTER_SIZE); |
8cfb12bf RH |
2791 | |
2792 | for (i = 0; VEC_iterate (tree, registered_class, i, klass); ++i) | |
cd9c7bd2 | 2793 | { |
8cfb12bf RH |
2794 | t = build_fold_addr_expr (klass); |
2795 | output_constant (t, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE); | |
cd9c7bd2 | 2796 | } |
6351543d AG |
2797 | } |
2798 | else | |
2799 | { | |
c9b9aa64 | 2800 | tree klass, t, register_class_fn; |
8cfb12bf | 2801 | int i; |
c9b9aa64 RH |
2802 | |
2803 | t = build_function_type_list (void_type_node, class_ptr_type, NULL); | |
2804 | t = build_decl (FUNCTION_DECL, get_identifier ("_Jv_RegisterClass"), t); | |
2805 | TREE_PUBLIC (t) = 1; | |
2806 | DECL_EXTERNAL (t) = 1; | |
2807 | register_class_fn = t; | |
2808 | ||
8cfb12bf | 2809 | for (i = 0; VEC_iterate (tree, registered_class, i, klass); ++i) |
c9b9aa64 RH |
2810 | { |
2811 | t = build_fold_addr_expr (klass); | |
5039610b | 2812 | t = build_call_expr (register_class_fn, 1, t); |
c9b9aa64 RH |
2813 | append_to_statement_list (t, list_p); |
2814 | } | |
6351543d | 2815 | } |
e04a16fb AG |
2816 | } |
2817 | ||
9dfc2ec2 | 2818 | /* Make a symbol_type (_Jv_MethodSymbol) node for DECL. */ |
861ef928 | 2819 | |
8ce33230 | 2820 | static tree |
313ab5ee | 2821 | build_symbol_entry (tree decl, tree special) |
861ef928 | 2822 | { |
9dfc2ec2 | 2823 | tree clname, name, signature, sym; |
9dfc2ec2 | 2824 | clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl)))); |
36739040 TT |
2825 | /* ??? Constructors are given the name foo.foo all the way through |
2826 | the compiler, but in the method table they're all renamed | |
2827 | foo.<init>. So, we have to do the same here unless we want an | |
2828 | unresolved reference at runtime. */ | |
2829 | name = build_utf8_ref ((TREE_CODE (decl) == FUNCTION_DECL | |
2830 | && DECL_CONSTRUCTOR_P (decl)) | |
2831 | ? init_identifier_node | |
2832 | : DECL_NAME (decl)); | |
9dfc2ec2 | 2833 | signature = build_java_signature (TREE_TYPE (decl)); |
861ef928 BM |
2834 | signature = build_utf8_ref (unmangle_classname |
2835 | (IDENTIFIER_POINTER (signature), | |
2836 | IDENTIFIER_LENGTH (signature))); | |
313ab5ee AH |
2837 | /* SPECIAL is either NULL_TREE or integer_one_node. We emit |
2838 | signature addr+1 if SPECIAL, and this indicates to the runtime | |
2839 | system that this is a "special" symbol, i.e. one that should | |
2840 | bypass access controls. */ | |
2841 | if (special != NULL_TREE) | |
5be014d5 AP |
2842 | signature = build2 (POINTER_PLUS_EXPR, TREE_TYPE (signature), signature, |
2843 | fold_convert (sizetype, special)); | |
36739040 | 2844 | |
9dfc2ec2 AH |
2845 | START_RECORD_CONSTRUCTOR (sym, symbol_type); |
2846 | PUSH_FIELD_VALUE (sym, "clname", clname); | |
2847 | PUSH_FIELD_VALUE (sym, "name", name); | |
2848 | PUSH_FIELD_VALUE (sym, "signature", signature); | |
2849 | FINISH_RECORD_CONSTRUCTOR (sym); | |
2850 | TREE_CONSTANT (sym) = 1; | |
861ef928 | 2851 | |
9dfc2ec2 | 2852 | return sym; |
861ef928 BM |
2853 | } |
2854 | ||
9dfc2ec2 | 2855 | /* Emit a symbol table: used by -findirect-dispatch. */ |
861ef928 | 2856 | |
9dfc2ec2 | 2857 | tree |
fe0b9fb5 | 2858 | emit_symbol_table (tree name, tree the_table, tree decl_list, |
36739040 TT |
2859 | tree the_syms_decl, tree the_array_element_type, |
2860 | int element_size) | |
861ef928 BM |
2861 | { |
2862 | tree method_list, method, table, list, null_symbol; | |
9dfc2ec2 | 2863 | tree table_size, the_array_type; |
861ef928 BM |
2864 | int index; |
2865 | ||
9dfc2ec2 AH |
2866 | /* Only emit a table if this translation unit actually made any |
2867 | references via it. */ | |
2868 | if (decl_list == NULL_TREE) | |
2869 | return the_table; | |
861ef928 BM |
2870 | |
2871 | /* Build a list of _Jv_MethodSymbols for each entry in otable_methods. */ | |
2872 | index = 0; | |
9dfc2ec2 | 2873 | method_list = decl_list; |
861ef928 BM |
2874 | list = NULL_TREE; |
2875 | while (method_list != NULL_TREE) | |
2876 | { | |
313ab5ee | 2877 | tree special = TREE_PURPOSE (method_list); |
861ef928 | 2878 | method = TREE_VALUE (method_list); |
313ab5ee | 2879 | list = tree_cons (NULL_TREE, build_symbol_entry (method, special), list); |
861ef928 BM |
2880 | method_list = TREE_CHAIN (method_list); |
2881 | index++; | |
2882 | } | |
2883 | ||
2884 | /* Terminate the list with a "null" entry. */ | |
9dfc2ec2 | 2885 | START_RECORD_CONSTRUCTOR (null_symbol, symbol_type); |
861ef928 BM |
2886 | PUSH_FIELD_VALUE (null_symbol, "clname", null_pointer_node); |
2887 | PUSH_FIELD_VALUE (null_symbol, "name", null_pointer_node); | |
2888 | PUSH_FIELD_VALUE (null_symbol, "signature", null_pointer_node); | |
2889 | FINISH_RECORD_CONSTRUCTOR (null_symbol); | |
2890 | TREE_CONSTANT (null_symbol) = 1; | |
2891 | list = tree_cons (NULL_TREE, null_symbol, list); | |
2892 | ||
2893 | /* Put the list in the right order and make it a constructor. */ | |
2894 | list = nreverse (list); | |
4038c495 | 2895 | table = build_constructor_from_list (symbols_array_type, list); |
861ef928 BM |
2896 | |
2897 | /* Make it the initial value for otable_syms and emit the decl. */ | |
9dfc2ec2 AH |
2898 | DECL_INITIAL (the_syms_decl) = table; |
2899 | DECL_ARTIFICIAL (the_syms_decl) = 1; | |
2900 | DECL_IGNORED_P (the_syms_decl) = 1; | |
0e6df31e | 2901 | rest_of_decl_compilation (the_syms_decl, 1, 0); |
861ef928 | 2902 | |
9dfc2ec2 AH |
2903 | /* Now that its size is known, redefine the table as an |
2904 | uninitialized static array of INDEX + 1 elements. The extra entry | |
2905 | is used by the runtime to track whether the table has been | |
2906 | initialized. */ | |
36739040 TT |
2907 | table_size |
2908 | = build_index_type (build_int_cst (NULL_TREE, index * element_size + 1)); | |
9dfc2ec2 AH |
2909 | the_array_type = build_array_type (the_array_element_type, table_size); |
2910 | the_table = build_decl (VAR_DECL, name, the_array_type); | |
2911 | TREE_STATIC (the_table) = 1; | |
2912 | TREE_READONLY (the_table) = 1; | |
0e6df31e | 2913 | rest_of_decl_compilation (the_table, 1, 0); |
9dfc2ec2 AH |
2914 | |
2915 | return the_table; | |
861ef928 BM |
2916 | } |
2917 | ||
36739040 | 2918 | /* Make an entry for the catch_classes list. */ |
90471585 AH |
2919 | tree |
2920 | make_catch_class_record (tree catch_class, tree classname) | |
2921 | { | |
2922 | tree entry; | |
85194ee9 | 2923 | tree type = TREE_TYPE (TREE_TYPE (TYPE_CTABLE_DECL (output_class))); |
90471585 AH |
2924 | START_RECORD_CONSTRUCTOR (entry, type); |
2925 | PUSH_FIELD_VALUE (entry, "address", catch_class); | |
2926 | PUSH_FIELD_VALUE (entry, "classname", classname); | |
2927 | FINISH_RECORD_CONSTRUCTOR (entry); | |
2928 | return entry; | |
2929 | } | |
2930 | ||
2931 | ||
2932 | /* Generate the list of Throwable classes that are caught by exception | |
85194ee9 AH |
2933 | handlers in this class. */ |
2934 | tree | |
2935 | emit_catch_table (tree this_class) | |
90471585 AH |
2936 | { |
2937 | tree table, table_size, array_type; | |
85194ee9 AH |
2938 | TYPE_CATCH_CLASSES (this_class) = |
2939 | tree_cons (NULL, | |
2940 | make_catch_class_record (null_pointer_node, null_pointer_node), | |
2941 | TYPE_CATCH_CLASSES (this_class)); | |
2942 | TYPE_CATCH_CLASSES (this_class) = nreverse (TYPE_CATCH_CLASSES (this_class)); | |
2943 | TYPE_CATCH_CLASSES (this_class) = | |
2944 | tree_cons (NULL, | |
2945 | make_catch_class_record (null_pointer_node, null_pointer_node), | |
2946 | TYPE_CATCH_CLASSES (this_class)); | |
4a90aeeb NS |
2947 | table_size = build_index_type |
2948 | (build_int_cst (NULL_TREE, | |
7d60be94 | 2949 | list_length (TYPE_CATCH_CLASSES (this_class)))); |
90471585 | 2950 | array_type |
85194ee9 AH |
2951 | = build_array_type (TREE_TYPE (TREE_TYPE (TYPE_CTABLE_DECL (this_class))), |
2952 | table_size); | |
2953 | table = | |
2954 | build_decl (VAR_DECL, DECL_NAME (TYPE_CTABLE_DECL (this_class)), array_type); | |
2955 | DECL_INITIAL (table) = | |
4038c495 | 2956 | build_constructor_from_list (array_type, TYPE_CATCH_CLASSES (this_class)); |
90471585 AH |
2957 | TREE_STATIC (table) = 1; |
2958 | TREE_READONLY (table) = 1; | |
85194ee9 | 2959 | DECL_IGNORED_P (table) = 1; |
0e6df31e | 2960 | rest_of_decl_compilation (table, 1, 0); |
85194ee9 | 2961 | return table; |
90471585 | 2962 | } |
36739040 TT |
2963 | |
2964 | /* Given a type, return the signature used by | |
2965 | _Jv_FindClassFromSignature() in libgcj. This isn't exactly the | |
2966 | same as build_java_signature() because we want the canonical array | |
2967 | type. */ | |
2968 | ||
2969 | static tree | |
2970 | build_signature_for_libgcj (tree type) | |
2971 | { | |
2972 | tree sig, ref; | |
2973 | ||
2974 | sig = build_java_signature (type); | |
2975 | ref = build_utf8_ref (unmangle_classname (IDENTIFIER_POINTER (sig), | |
2976 | IDENTIFIER_LENGTH (sig))); | |
2977 | return ref; | |
2978 | } | |
2979 | ||
2980 | /* Add an entry to the type assertion table. Callback used during hashtable | |
2981 | traversal. */ | |
2982 | ||
2983 | static int | |
2984 | add_assertion_table_entry (void **htab_entry, void *ptr) | |
2985 | { | |
2986 | tree entry; | |
2987 | tree code_val, op1_utf8, op2_utf8; | |
2988 | tree *list = (tree *) ptr; | |
2989 | type_assertion *as = (type_assertion *) *htab_entry; | |
2990 | ||
2991 | code_val = build_int_cst (NULL_TREE, as->assertion_code); | |
2992 | ||
2993 | if (as->op1 == NULL_TREE) | |
2994 | op1_utf8 = null_pointer_node; | |
2995 | else | |
2996 | op1_utf8 = build_signature_for_libgcj (as->op1); | |
2997 | ||
2998 | if (as->op2 == NULL_TREE) | |
2999 | op2_utf8 = null_pointer_node; | |
3000 | else | |
3001 | op2_utf8 = build_signature_for_libgcj (as->op2); | |
3002 | ||
3003 | START_RECORD_CONSTRUCTOR (entry, assertion_entry_type); | |
3004 | PUSH_FIELD_VALUE (entry, "assertion_code", code_val); | |
3005 | PUSH_FIELD_VALUE (entry, "op1", op1_utf8); | |
3006 | PUSH_FIELD_VALUE (entry, "op2", op2_utf8); | |
3007 | FINISH_RECORD_CONSTRUCTOR (entry); | |
3008 | ||
3009 | *list = tree_cons (NULL_TREE, entry, *list); | |
3010 | return true; | |
3011 | } | |
3012 | ||
3013 | /* Generate the type assertion table for CLASS, and return its DECL. */ | |
3014 | ||
3015 | static tree | |
3016 | emit_assertion_table (tree class) | |
3017 | { | |
3018 | tree null_entry, ctor, table_decl; | |
3019 | tree list = NULL_TREE; | |
3020 | htab_t assertions_htab = TYPE_ASSERTIONS (class); | |
3021 | ||
3022 | /* Iterate through the hash table. */ | |
3023 | htab_traverse (assertions_htab, add_assertion_table_entry, &list); | |
3024 | ||
3025 | /* Finish with a null entry. */ | |
3026 | START_RECORD_CONSTRUCTOR (null_entry, assertion_entry_type); | |
3027 | PUSH_FIELD_VALUE (null_entry, "assertion_code", integer_zero_node); | |
3028 | PUSH_FIELD_VALUE (null_entry, "op1", null_pointer_node); | |
3029 | PUSH_FIELD_VALUE (null_entry, "op2", null_pointer_node); | |
3030 | FINISH_RECORD_CONSTRUCTOR (null_entry); | |
3031 | ||
3032 | list = tree_cons (NULL_TREE, null_entry, list); | |
3033 | ||
3034 | /* Put the list in the right order and make it a constructor. */ | |
3035 | list = nreverse (list); | |
4038c495 | 3036 | ctor = build_constructor_from_list (assertion_table_type, list); |
36739040 TT |
3037 | |
3038 | table_decl = build_decl (VAR_DECL, mangled_classname ("_type_assert_", class), | |
3039 | assertion_table_type); | |
3040 | ||
3041 | TREE_STATIC (table_decl) = 1; | |
3042 | TREE_READONLY (table_decl) = 1; | |
3043 | TREE_CONSTANT (table_decl) = 1; | |
3044 | DECL_IGNORED_P (table_decl) = 1; | |
3045 | ||
3046 | DECL_INITIAL (table_decl) = ctor; | |
3047 | DECL_ARTIFICIAL (table_decl) = 1; | |
3048 | rest_of_decl_compilation (table_decl, 1, 0); | |
3049 | ||
3050 | return table_decl; | |
3051 | } | |
90471585 | 3052 | |
e04a16fb | 3053 | void |
0a2f0c54 | 3054 | init_class_processing (void) |
e04a16fb | 3055 | { |
b5c4fed9 PB |
3056 | fields_ident = get_identifier ("fields"); |
3057 | info_ident = get_identifier ("info"); | |
c9b9aa64 | 3058 | |
1f8f4a0b | 3059 | gcc_obstack_init (&temporary_obstack); |
e04a16fb | 3060 | } |
e2500fed | 3061 | \f |
d2097937 KG |
3062 | static hashval_t java_treetreehash_hash (const void *); |
3063 | static int java_treetreehash_compare (const void *, const void *); | |
e2500fed GK |
3064 | |
3065 | /* A hash table mapping trees to trees. Used generally. */ | |
3066 | ||
0ab57536 | 3067 | #define JAVA_TREEHASHHASH_H(t) ((hashval_t)TYPE_UID (t)) |
e2500fed GK |
3068 | |
3069 | static hashval_t | |
0a2f0c54 | 3070 | java_treetreehash_hash (const void *k_p) |
e2500fed | 3071 | { |
741ac903 KG |
3072 | const struct treetreehash_entry *const k |
3073 | = (const struct treetreehash_entry *) k_p; | |
e2500fed GK |
3074 | return JAVA_TREEHASHHASH_H (k->key); |
3075 | } | |
3076 | ||
3077 | static int | |
0a2f0c54 | 3078 | java_treetreehash_compare (const void * k1_p, const void * k2_p) |
e2500fed | 3079 | { |
741ac903 KG |
3080 | const struct treetreehash_entry *const k1 |
3081 | = (const struct treetreehash_entry *) k1_p; | |
3082 | const_tree const k2 = (const_tree) k2_p; | |
e2500fed GK |
3083 | return (k1->key == k2); |
3084 | } | |
3085 | ||
3086 | tree | |
0a2f0c54 | 3087 | java_treetreehash_find (htab_t ht, tree t) |
e2500fed GK |
3088 | { |
3089 | struct treetreehash_entry *e; | |
3090 | hashval_t hv = JAVA_TREEHASHHASH_H (t); | |
c68b0a84 | 3091 | e = htab_find_with_hash (ht, t, hv); |
e2500fed GK |
3092 | if (e == NULL) |
3093 | return NULL; | |
3094 | else | |
3095 | return e->value; | |
3096 | } | |
3097 | ||
3098 | tree * | |
0a2f0c54 | 3099 | java_treetreehash_new (htab_t ht, tree t) |
e2500fed | 3100 | { |
77d3109b | 3101 | void **e; |
e2500fed GK |
3102 | struct treetreehash_entry *tthe; |
3103 | hashval_t hv = JAVA_TREEHASHHASH_H (t); | |
3104 | ||
3105 | e = htab_find_slot_with_hash (ht, t, hv, INSERT); | |
3106 | if (*e == NULL) | |
3107 | { | |
3108 | tthe = (*ht->alloc_f) (1, sizeof (*tthe)); | |
3109 | tthe->key = t; | |
77d3109b | 3110 | *e = tthe; |
e2500fed GK |
3111 | } |
3112 | else | |
3113 | tthe = (struct treetreehash_entry *) *e; | |
3114 | return &tthe->value; | |
3115 | } | |
3116 | ||
3117 | htab_t | |
0a2f0c54 | 3118 | java_treetreehash_create (size_t size, int gc) |
e2500fed GK |
3119 | { |
3120 | if (gc) | |
3121 | return htab_create_ggc (size, java_treetreehash_hash, | |
3122 | java_treetreehash_compare, NULL); | |
3123 | else | |
3124 | return htab_create_alloc (size, java_treetreehash_hash, | |
3125 | java_treetreehash_compare, free, xcalloc, free); | |
3126 | } | |
3127 | ||
9c5fdae6 BM |
3128 | /* Break down qualified IDENTIFIER into package and class-name components. |
3129 | For example, given SOURCE "pkg.foo.Bar", LEFT will be set to | |
3130 | "pkg.foo", and RIGHT to "Bar". */ | |
3131 | ||
3132 | int | |
3133 | split_qualified_name (tree *left, tree *right, tree source) | |
3134 | { | |
3135 | char *p, *base; | |
3136 | int l = IDENTIFIER_LENGTH (source); | |
3137 | ||
3138 | base = alloca (l + 1); | |
3139 | memcpy (base, IDENTIFIER_POINTER (source), l + 1); | |
3140 | ||
3141 | /* Breakdown NAME into REMAINDER . IDENTIFIER. */ | |
3142 | p = base + l - 1; | |
3143 | while (*p != '.' && p != base) | |
3144 | p--; | |
3145 | ||
3146 | /* We didn't find a '.'. Return an error. */ | |
3147 | if (p == base) | |
3148 | return 1; | |
3149 | ||
3150 | *p = '\0'; | |
3151 | if (right) | |
3152 | *right = get_identifier (p+1); | |
3153 | *left = get_identifier (base); | |
3154 | ||
3155 | return 0; | |
3156 | } | |
3157 | ||
3158 | /* Given two classes (TYPE_DECL) or class names (IDENTIFIER), return TRUE | |
3159 | if the classes are from the same package. */ | |
3160 | ||
3161 | int | |
3162 | in_same_package (tree name1, tree name2) | |
3163 | { | |
3164 | tree tmp; | |
3165 | tree pkg1; | |
3166 | tree pkg2; | |
3167 | ||
3168 | if (TREE_CODE (name1) == TYPE_DECL) | |
3169 | name1 = DECL_NAME (name1); | |
3170 | if (TREE_CODE (name2) == TYPE_DECL) | |
3171 | name2 = DECL_NAME (name2); | |
3172 | ||
3173 | if (QUALIFIED_P (name1) != QUALIFIED_P (name2)) | |
3174 | /* One in empty package. */ | |
3175 | return 0; | |
3176 | ||
3177 | if (QUALIFIED_P (name1) == 0 && QUALIFIED_P (name2) == 0) | |
3178 | /* Both in empty package. */ | |
3179 | return 1; | |
3180 | ||
3181 | split_qualified_name (&pkg1, &tmp, name1); | |
3182 | split_qualified_name (&pkg2, &tmp, name2); | |
3183 | ||
3184 | return (pkg1 == pkg2); | |
3185 | } | |
3186 | ||
e2500fed | 3187 | #include "gt-java-class.h" |