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