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