]>
Commit | Line | Data |
---|---|---|
e04a16fb | 1 | /* Java(TM) language-specific utility routines. |
85194ee9 | 2 | Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 |
a5a4ce3c | 3 | Free Software Foundation, Inc. |
e04a16fb | 4 | |
f309ff0a | 5 | This file is part of GCC. |
e04a16fb | 6 | |
f309ff0a | 7 | GCC is free software; you can redistribute it and/or modify |
e04a16fb AG |
8 | it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
f309ff0a | 12 | GCC is distributed in the hope that it will be useful, |
e04a16fb AG |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
f309ff0a | 18 | along with GCC; see the file COPYING. If not, write to |
e04a16fb AG |
19 | the Free Software Foundation, 59 Temple Place - Suite 330, |
20 | Boston, MA 02111-1307, USA. | |
21 | ||
22 | Java and all Java-based marks are trademarks or registered trademarks | |
23 | of Sun Microsystems, Inc. in the United States and other countries. | |
24 | The Free Software Foundation is independent of Sun Microsystems, Inc. */ | |
25 | ||
26 | /* Hacked by Per Bothner <bothner@cygnus.com> February 1996. */ | |
27 | ||
e04a16fb | 28 | #include "config.h" |
1f43f4b4 | 29 | #include "system.h" |
4977bab6 ZW |
30 | #include "coretypes.h" |
31 | #include "tm.h" | |
e04a16fb AG |
32 | #include "tree.h" |
33 | #include "input.h" | |
49f48c71 KG |
34 | #include "rtl.h" |
35 | #include "expr.h" | |
e04a16fb AG |
36 | #include "java-tree.h" |
37 | #include "jcf.h" | |
1f43f4b4 | 38 | #include "toplev.h" |
c83303d8 | 39 | #include "langhooks.h" |
d23c55c2 | 40 | #include "langhooks-def.h" |
fc45c7ef | 41 | #include "flags.h" |
235acd35 | 42 | #include "xref.h" |
19e223db | 43 | #include "ggc.h" |
46f018e1 | 44 | #include "diagnostic.h" |
7149627b | 45 | #include "tree-inline.h" |
3eb429b2 | 46 | #include "splay-tree.h" |
c1ddb5c8 | 47 | #include "tree-dump.h" |
c8b04b13 | 48 | #include "opts.h" |
d7b42618 | 49 | #include "options.h" |
b7436b72 | 50 | |
4bfec483 | 51 | static bool java_init (void); |
d2097937 | 52 | static void java_finish (void); |
b86f6cd9 | 53 | static unsigned int java_init_options (unsigned int, const char **); |
4bfec483 | 54 | static bool java_post_options (const char **); |
36d010ca | 55 | |
95ca6d8b | 56 | static int java_handle_option (size_t scode, const char *arg, int value); |
d2097937 KG |
57 | static void put_decl_string (const char *, int); |
58 | static void put_decl_node (tree); | |
59 | static void java_print_error_function (diagnostic_context *, const char *); | |
d2097937 KG |
60 | static tree java_tree_inlining_walk_subtrees (tree *, int *, walk_tree_fn, |
61 | void *, void *); | |
62 | static int java_unsafe_for_reeval (tree); | |
63 | static int merge_init_test_initialization (void * *, void *); | |
64 | static int inline_init_test_initialization (void * *, void *); | |
65 | static bool java_can_use_bit_fields_p (void); | |
2bd3ecad | 66 | static bool java_dump_tree (void *, tree); |
d2097937 | 67 | static void dump_compound_expr (dump_info_p, tree); |
e076f71a | 68 | static bool java_decl_ok_for_sibcall (tree); |
90471585 | 69 | static tree java_get_callee_fndecl (tree); |
0d811e1a | 70 | |
45936a85 DD |
71 | #ifndef TARGET_OBJECT_SUFFIX |
72 | # define TARGET_OBJECT_SUFFIX ".o" | |
8603f9c5 TT |
73 | #endif |
74 | ||
e4de5a10 PB |
75 | /* Table indexed by tree code giving a string containing a character |
76 | classifying the tree code. Possibilities are | |
77 | t, d, s, c, r, <, 1 and 2. See java/java-tree.def for details. */ | |
78 | ||
79 | #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE, | |
80 | ||
2f9834e8 KG |
81 | const char tree_code_type[] = { |
82 | #include "tree.def" | |
e4de5a10 PB |
83 | 'x', |
84 | #include "java-tree.def" | |
85 | }; | |
86 | #undef DEFTREECODE | |
87 | ||
88 | /* Table indexed by tree code giving number of expression | |
89 | operands beyond the fixed part of the node structure. | |
90 | Not used for types or decls. */ | |
91 | ||
92 | #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH, | |
93 | ||
2f9834e8 KG |
94 | const unsigned char tree_code_length[] = { |
95 | #include "tree.def" | |
e4de5a10 PB |
96 | 0, |
97 | #include "java-tree.def" | |
98 | }; | |
99 | #undef DEFTREECODE | |
100 | ||
101 | /* Names of tree components. | |
102 | Used for printing out the tree and error messages. */ | |
103 | #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME, | |
104 | ||
2f9834e8 KG |
105 | const char *const tree_code_name[] = { |
106 | #include "tree.def" | |
e4de5a10 PB |
107 | "@@dummy", |
108 | #include "java-tree.def" | |
109 | }; | |
110 | #undef DEFTREECODE | |
111 | ||
7cb32822 NB |
112 | /* Used to avoid printing error messages with bogus function |
113 | prototypes. Starts out false. */ | |
114 | static bool inhibit_error_function_printing; | |
115 | ||
e04a16fb AG |
116 | int compiling_from_source; |
117 | ||
95ca6d8b | 118 | const char *resource_name; |
7be5b0e5 | 119 | |
e04a16fb AG |
120 | int flag_emit_class_files = 0; |
121 | ||
fea2d5da PB |
122 | /* Nonzero if input file is a file with a list of filenames to compile. */ |
123 | ||
124 | int flag_filelist_file = 0; | |
125 | ||
ee142fe7 | 126 | /* When nonzero, we emit xref strings. Values of the flag for xref |
235acd35 APB |
127 | backends are defined in xref_flag_table, xref.c. */ |
128 | ||
129 | int flag_emit_xref = 0; | |
130 | ||
ee142fe7 | 131 | /* When nonzero, -Wall was turned on. */ |
c877974e APB |
132 | int flag_wall = 0; |
133 | ||
ee142fe7 | 134 | /* When nonzero, check for redundant modifier uses. */ |
c877974e APB |
135 | int flag_redundant = 0; |
136 | ||
ee142fe7 | 137 | /* When nonzero, call a library routine to do integer divisions. */ |
aa4759c1 AH |
138 | int flag_use_divide_subroutine = 1; |
139 | ||
ee142fe7 | 140 | /* When nonzero, generate code for the Boehm GC. */ |
5830574a TT |
141 | int flag_use_boehm_gc = 0; |
142 | ||
ee142fe7 | 143 | /* When nonzero, assume the runtime uses a hash table to map an |
64aa33dd TT |
144 | object to its synchronization structure. */ |
145 | int flag_hash_synchronization; | |
146 | ||
acc59b85 AG |
147 | /* When nonzero, permit the use of the assert keyword. */ |
148 | int flag_assert = 1; | |
149 | ||
ee142fe7 | 150 | /* When nonzero, assume all native functions are implemented with |
7145d9fe TT |
151 | JNI, not CNI. */ |
152 | int flag_jni = 0; | |
153 | ||
ee142fe7 | 154 | /* When nonzero, warn when source file is newer than matching class |
b7436b72 TT |
155 | file. */ |
156 | int flag_newer = 1; | |
157 | ||
ee142fe7 | 158 | /* When nonzero, generate checks for references to NULL. */ |
4ff17c6a AH |
159 | int flag_check_references = 0; |
160 | ||
d19cbcb5 | 161 | /* The encoding of the source file. */ |
a93eddcf | 162 | const char *current_encoding = NULL; |
d19cbcb5 | 163 | |
ee142fe7 | 164 | /* When nonzero, report the now deprecated empty statements. */ |
5f1c312a APB |
165 | int flag_extraneous_semicolon; |
166 | ||
f94ae540 TT |
167 | /* When nonzero, report use of deprecated classes, methods, or fields. */ |
168 | int flag_deprecated = 1; | |
169 | ||
ee142fe7 | 170 | /* When nonzero, always check for a non gcj generated classes archive. */ |
b124f72e APB |
171 | int flag_force_classes_archive_check; |
172 | ||
4009bb7d APB |
173 | /* When zero, don't optimize static class initialization. This flag shouldn't |
174 | be tested alone, use STATIC_CLASS_INITIALIZATION_OPTIMIZATION_P instead. */ | |
6de9cd9a DN |
175 | /* FIXME: Make this work with gimplify. */ |
176 | int flag_optimize_sci = 0; | |
4009bb7d | 177 | |
ee142fe7 | 178 | /* When nonzero, use offset tables for virtual method calls |
861ef928 BM |
179 | in order to improve binary compatibility. */ |
180 | int flag_indirect_dispatch = 0; | |
181 | ||
022dcc46 BM |
182 | /* When zero, don't generate runtime array store checks. */ |
183 | int flag_store_check = 1; | |
184 | ||
ee142fe7 | 185 | /* When nonzero, print extra version information. */ |
d185d268 | 186 | static int v_flag = 0; |
4266d0b2 | 187 | |
ee142fe7 | 188 | /* Set nonzero if the user specified -finline-functions on the command |
36d010ca BM |
189 | line. */ |
190 | int flag_really_inline = 0; | |
191 | ||
e04a16fb AG |
192 | JCF *current_jcf; |
193 | ||
fc45c7ef | 194 | /* Variable controlling how dependency tracking is enabled in |
f5e99456 | 195 | java_init. */ |
fc45c7ef TT |
196 | static int dependency_tracking = 0; |
197 | ||
198 | /* Flag values for DEPENDENCY_TRACKING. */ | |
199 | #define DEPEND_SET_FILE 1 | |
200 | #define DEPEND_ENABLE 2 | |
316a06a1 TT |
201 | #define DEPEND_TARGET_SET 4 |
202 | #define DEPEND_FILE_ALREADY_SET 8 | |
fc45c7ef | 203 | |
e2500fed GK |
204 | struct language_function GTY(()) |
205 | { | |
206 | int unused; | |
207 | }; | |
208 | ||
3ac88239 NB |
209 | #undef LANG_HOOKS_NAME |
210 | #define LANG_HOOKS_NAME "GNU Java" | |
c83303d8 APB |
211 | #undef LANG_HOOKS_INIT |
212 | #define LANG_HOOKS_INIT java_init | |
22703ccc NB |
213 | #undef LANG_HOOKS_FINISH |
214 | #define LANG_HOOKS_FINISH java_finish | |
c83303d8 APB |
215 | #undef LANG_HOOKS_INIT_OPTIONS |
216 | #define LANG_HOOKS_INIT_OPTIONS java_init_options | |
95ca6d8b NB |
217 | #undef LANG_HOOKS_HANDLE_OPTION |
218 | #define LANG_HOOKS_HANDLE_OPTION java_handle_option | |
36d010ca BM |
219 | #undef LANG_HOOKS_POST_OPTIONS |
220 | #define LANG_HOOKS_POST_OPTIONS java_post_options | |
52dabb6c NB |
221 | #undef LANG_HOOKS_PARSE_FILE |
222 | #define LANG_HOOKS_PARSE_FILE java_parse_file | |
8943a0b4 RH |
223 | #undef LANG_HOOKS_UNSAFE_FOR_REEVAL |
224 | #define LANG_HOOKS_UNSAFE_FOR_REEVAL java_unsafe_for_reeval | |
dffd7eb6 NB |
225 | #undef LANG_HOOKS_MARK_ADDRESSABLE |
226 | #define LANG_HOOKS_MARK_ADDRESSABLE java_mark_addressable | |
c9d892a8 NB |
227 | #undef LANG_HOOKS_EXPAND_EXPR |
228 | #define LANG_HOOKS_EXPAND_EXPR java_expand_expr | |
78ef5b89 NB |
229 | #undef LANG_HOOKS_TRUTHVALUE_CONVERSION |
230 | #define LANG_HOOKS_TRUTHVALUE_CONVERSION java_truthvalue_conversion | |
63e1b1c4 NB |
231 | #undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL |
232 | #define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL java_dup_lang_specific_decl | |
7afff7cf NB |
233 | #undef LANG_HOOKS_DECL_PRINTABLE_NAME |
234 | #define LANG_HOOKS_DECL_PRINTABLE_NAME lang_printable_name | |
7cb32822 NB |
235 | #undef LANG_HOOKS_PRINT_ERROR_FUNCTION |
236 | #define LANG_HOOKS_PRINT_ERROR_FUNCTION java_print_error_function | |
0d811e1a TT |
237 | #undef LANG_HOOKS_CAN_USE_BIT_FIELDS_P |
238 | #define LANG_HOOKS_CAN_USE_BIT_FIELDS_P java_can_use_bit_fields_p | |
ceef8ce4 | 239 | |
b0c48229 NB |
240 | #undef LANG_HOOKS_TYPE_FOR_MODE |
241 | #define LANG_HOOKS_TYPE_FOR_MODE java_type_for_mode | |
242 | #undef LANG_HOOKS_TYPE_FOR_SIZE | |
243 | #define LANG_HOOKS_TYPE_FOR_SIZE java_type_for_size | |
ceef8ce4 NB |
244 | #undef LANG_HOOKS_SIGNED_TYPE |
245 | #define LANG_HOOKS_SIGNED_TYPE java_signed_type | |
246 | #undef LANG_HOOKS_UNSIGNED_TYPE | |
247 | #define LANG_HOOKS_UNSIGNED_TYPE java_unsigned_type | |
248 | #undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE | |
249 | #define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE java_signed_or_unsigned_type | |
c83303d8 | 250 | |
c1ddb5c8 AH |
251 | #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN |
252 | #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN java_dump_tree | |
253 | ||
6de9cd9a DN |
254 | #undef LANG_HOOKS_GIMPLIFY_EXPR |
255 | #define LANG_HOOKS_GIMPLIFY_EXPR java_gimplify_expr | |
256 | ||
257 | #undef LANG_HOOKS_TREE_INLINING_WALK_SUBTREES | |
258 | #define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES java_tree_inlining_walk_subtrees | |
259 | ||
e076f71a AH |
260 | #undef LANG_HOOKS_DECL_OK_FOR_SIBCALL |
261 | #define LANG_HOOKS_DECL_OK_FOR_SIBCALL java_decl_ok_for_sibcall | |
262 | ||
90471585 AH |
263 | #undef LANG_HOOKS_GET_CALLEE_FNDECL |
264 | #define LANG_HOOKS_GET_CALLEE_FNDECL java_get_callee_fndecl | |
265 | ||
916b57ce JS |
266 | #undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION |
267 | #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION java_expand_body | |
268 | ||
cd2a3ba2 | 269 | /* Each front end provides its own. */ |
3ac88239 | 270 | const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; |
cd2a3ba2 | 271 | |
e04a16fb AG |
272 | /* |
273 | * process java-specific compiler command-line options | |
6522685d | 274 | * return 0, but do not complain if the option is not recognized. |
e04a16fb | 275 | */ |
ee811cfd | 276 | static int |
95ca6d8b | 277 | java_handle_option (size_t scode, const char *arg, int value) |
e04a16fb | 278 | { |
95ca6d8b | 279 | enum opt_code code = (enum opt_code) scode; |
2a85660d | 280 | |
95ca6d8b | 281 | switch (code) |
e04a16fb | 282 | { |
95ca6d8b | 283 | default: |
d7b42618 | 284 | abort(); |
e04a16fb | 285 | |
95ca6d8b NB |
286 | case OPT_I: |
287 | jcf_path_include_arg (arg); | |
288 | break; | |
7f10c2e2 | 289 | |
95ca6d8b NB |
290 | case OPT_M: |
291 | jcf_dependency_init (1); | |
292 | dependency_tracking |= DEPEND_ENABLE; | |
293 | break; | |
5f1c312a | 294 | |
cef67dce | 295 | case OPT_MD_: |
fc45c7ef TT |
296 | jcf_dependency_init (1); |
297 | dependency_tracking |= DEPEND_SET_FILE | DEPEND_ENABLE; | |
95ca6d8b NB |
298 | break; |
299 | ||
300 | case OPT_MF: | |
301 | jcf_dependency_set_dep_file (arg); | |
4a09cbac | 302 | dependency_tracking |= DEPEND_FILE_ALREADY_SET; |
95ca6d8b NB |
303 | break; |
304 | ||
305 | case OPT_MM: | |
fc45c7ef | 306 | jcf_dependency_init (0); |
fc45c7ef | 307 | dependency_tracking |= DEPEND_ENABLE; |
95ca6d8b NB |
308 | break; |
309 | ||
cef67dce | 310 | case OPT_MMD_: |
fc45c7ef | 311 | jcf_dependency_init (0); |
95ca6d8b NB |
312 | dependency_tracking |= DEPEND_SET_FILE | DEPEND_ENABLE; |
313 | break; | |
314 | ||
315 | case OPT_MP: | |
316a06a1 | 316 | jcf_dependency_print_dummies (); |
95ca6d8b NB |
317 | break; |
318 | ||
319 | case OPT_MT: | |
320 | jcf_dependency_set_target (arg); | |
316a06a1 | 321 | dependency_tracking |= DEPEND_TARGET_SET; |
95ca6d8b | 322 | break; |
fc45c7ef | 323 | |
95ca6d8b NB |
324 | case OPT_Wall: |
325 | flag_wall = value; | |
326 | flag_redundant = value; | |
327 | flag_extraneous_semicolon = value; | |
328 | /* When -Wall given, enable -Wunused. We do this because the C | |
329 | compiler does it, and people expect it. */ | |
330 | set_Wunused (value); | |
331 | break; | |
332 | ||
333 | case OPT_Wdeprecated: | |
334 | flag_deprecated = value; | |
335 | break; | |
336 | ||
337 | case OPT_Wextraneous_semicolon: | |
338 | flag_extraneous_semicolon = value; | |
339 | break; | |
340 | ||
341 | case OPT_Wout_of_date: | |
342 | flag_newer = value; | |
343 | break; | |
344 | ||
345 | case OPT_Wredundant_modifiers: | |
346 | flag_redundant = value; | |
347 | break; | |
348 | ||
349 | case OPT_fassert: | |
350 | flag_assert = value; | |
351 | break; | |
352 | ||
24d82bce PB |
353 | case OPT_fenable_assertions_: |
354 | add_enable_assert (arg, value); | |
355 | break; | |
356 | ||
357 | case OPT_fenable_assertions: | |
358 | add_enable_assert ("", value); | |
359 | break; | |
360 | ||
361 | case OPT_fdisable_assertions_: | |
362 | add_enable_assert (arg, !value); | |
363 | break; | |
364 | ||
365 | case OPT_fdisable_assertions: | |
366 | add_enable_assert ("", !value); | |
367 | break; | |
368 | ||
95ca6d8b NB |
369 | case OPT_fassume_compiled_: |
370 | add_assume_compiled (arg, !value); | |
371 | break; | |
372 | ||
373 | case OPT_fassume_compiled: | |
374 | add_assume_compiled ("", !value); | |
375 | break; | |
376 | ||
377 | case OPT_fbootclasspath_: | |
378 | jcf_path_bootclasspath_arg (arg); | |
379 | break; | |
380 | ||
381 | case OPT_fcheck_references: | |
382 | flag_check_references = value; | |
383 | break; | |
384 | ||
385 | case OPT_fclasspath_: | |
386 | case OPT_fCLASSPATH_: | |
387 | jcf_path_classpath_arg (arg); | |
388 | break; | |
389 | ||
390 | case OPT_fcompile_resource_: | |
391 | resource_name = arg; | |
392 | break; | |
393 | ||
394 | case OPT_fdump_: | |
f3f735eb | 395 | if (!dump_switch_p (arg)) |
265411b6 | 396 | return 0; |
95ca6d8b NB |
397 | break; |
398 | ||
399 | case OPT_femit_class_file: | |
400 | case OPT_femit_class_files: | |
401 | flag_emit_class_files = value; | |
402 | break; | |
403 | ||
404 | case OPT_fencoding_: | |
405 | current_encoding = arg; | |
406 | break; | |
407 | ||
408 | case OPT_fextdirs_: | |
409 | jcf_path_extdirs_arg (arg); | |
410 | break; | |
411 | ||
412 | case OPT_ffilelist_file: | |
413 | flag_filelist_file = value; | |
414 | break; | |
415 | ||
416 | case OPT_fforce_classes_archive_check: | |
417 | flag_force_classes_archive_check = value; | |
418 | break; | |
419 | ||
420 | case OPT_fhash_synchronization: | |
421 | flag_hash_synchronization = value; | |
422 | break; | |
423 | ||
424 | case OPT_findirect_dispatch: | |
425 | flag_indirect_dispatch = value; | |
426 | break; | |
427 | ||
428 | case OPT_finline_functions: | |
429 | flag_inline_functions = value; | |
430 | flag_really_inline = value; | |
431 | break; | |
432 | ||
433 | case OPT_fjni: | |
434 | flag_jni = value; | |
435 | break; | |
436 | ||
437 | case OPT_foptimize_static_class_initialization: | |
438 | flag_optimize_sci = value; | |
439 | break; | |
440 | ||
441 | case OPT_foutput_class_dir_: | |
442 | jcf_write_base_directory = arg; | |
443 | break; | |
444 | ||
445 | case OPT_fstore_check: | |
446 | flag_store_check = value; | |
447 | break; | |
448 | ||
449 | case OPT_fuse_boehm_gc: | |
450 | flag_use_boehm_gc = value; | |
451 | break; | |
452 | ||
453 | case OPT_fuse_divide_subroutine: | |
454 | flag_use_divide_subroutine = value; | |
455 | break; | |
456 | ||
457 | case OPT_version: | |
d185d268 | 458 | v_flag = 1; |
95ca6d8b NB |
459 | break; |
460 | } | |
461 | ||
462 | return 1; | |
e04a16fb AG |
463 | } |
464 | ||
d19cbcb5 | 465 | /* Global open file. */ |
e04a16fb | 466 | FILE *finput; |
d19cbcb5 | 467 | |
4bfec483 NB |
468 | static bool |
469 | java_init (void) | |
e04a16fb | 470 | { |
f5e99456 NB |
471 | #if 0 |
472 | extern int flag_minimal_debug; | |
473 | flag_minimal_debug = 0; | |
474 | #endif | |
475 | ||
7149627b AH |
476 | if (flag_inline_functions) |
477 | flag_inline_trees = 1; | |
478 | ||
85194ee9 AH |
479 | /* FIXME: Indirect dispatch isn't yet compatible with static class |
480 | init optimization. */ | |
481 | if (flag_indirect_dispatch) | |
482 | always_initialize_class_p = true; | |
483 | ||
f963b5d9 RS |
484 | /* Force minimum function alignment if g++ uses the least significant |
485 | bit of function pointers to store the virtual bit. This is required | |
486 | to keep vtables compatible. */ | |
487 | if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn | |
488 | && force_align_functions_log < 1) | |
489 | force_align_functions_log = 1; | |
490 | ||
d185d268 | 491 | jcf_path_seal (v_flag); |
f5e99456 | 492 | |
f5e99456 NB |
493 | java_init_decl_processing (); |
494 | ||
495 | using_eh_for_cleanups (); | |
496 | ||
4bfec483 | 497 | return true; |
e04a16fb AG |
498 | } |
499 | ||
22703ccc | 500 | static void |
0a2f0c54 | 501 | java_finish (void) |
e04a16fb | 502 | { |
fc45c7ef | 503 | jcf_dependency_write (); |
e04a16fb AG |
504 | } |
505 | ||
506 | /* Buffer used by lang_printable_name. */ | |
507 | static char *decl_buf = NULL; | |
508 | ||
509 | /* Allocated size of decl_buf. */ | |
510 | static int decl_buflen = 0; | |
511 | ||
512 | /* Length of used part of decl_buf; position for next character. */ | |
513 | static int decl_bufpos = 0; | |
514 | ||
515 | /* Append the string STR to decl_buf. | |
516 | It length is given by LEN; -1 means the string is nul-terminated. */ | |
517 | ||
518 | static void | |
0a2f0c54 | 519 | put_decl_string (const char *str, int len) |
e04a16fb AG |
520 | { |
521 | if (len < 0) | |
522 | len = strlen (str); | |
523 | if (decl_bufpos + len >= decl_buflen) | |
524 | { | |
525 | if (decl_buf == NULL) | |
526 | { | |
527 | decl_buflen = len + 100; | |
a92cb0c3 | 528 | decl_buf = xmalloc (decl_buflen); |
e04a16fb AG |
529 | } |
530 | else | |
531 | { | |
532 | decl_buflen *= 2; | |
a92cb0c3 | 533 | decl_buf = xrealloc (decl_buf, decl_buflen); |
e04a16fb AG |
534 | } |
535 | } | |
536 | strcpy (decl_buf + decl_bufpos, str); | |
537 | decl_bufpos += len; | |
538 | } | |
539 | ||
540 | /* Append to decl_buf a printable name for NODE. */ | |
541 | ||
542 | static void | |
0a2f0c54 | 543 | put_decl_node (tree node) |
e04a16fb AG |
544 | { |
545 | int was_pointer = 0; | |
546 | if (TREE_CODE (node) == POINTER_TYPE) | |
547 | { | |
548 | node = TREE_TYPE (node); | |
549 | was_pointer = 1; | |
550 | } | |
551 | if (TREE_CODE_CLASS (TREE_CODE (node)) == 'd' | |
552 | && DECL_NAME (node) != NULL_TREE) | |
553 | { | |
bc8a5e56 | 554 | if (TREE_CODE (node) == FUNCTION_DECL) |
2c36c7fd | 555 | { |
bc8a5e56 PB |
556 | /* We want to print the type the DECL belongs to. We don't do |
557 | that when we handle constructors. */ | |
558 | if (! DECL_CONSTRUCTOR_P (node) | |
559 | && ! DECL_ARTIFICIAL (node) && DECL_CONTEXT (node)) | |
e04a16fb | 560 | { |
bc8a5e56 PB |
561 | put_decl_node (TYPE_NAME (DECL_CONTEXT (node))); |
562 | put_decl_string (".", 1); | |
563 | } | |
564 | if (! DECL_CONSTRUCTOR_P (node)) | |
565 | put_decl_node (DECL_NAME (node)); | |
566 | if (TREE_TYPE (node) != NULL_TREE) | |
567 | { | |
568 | int i = 0; | |
569 | tree args = TYPE_ARG_TYPES (TREE_TYPE (node)); | |
570 | if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE) | |
571 | args = TREE_CHAIN (args); | |
572 | put_decl_string ("(", 1); | |
573 | for ( ; args != end_params_node; args = TREE_CHAIN (args), i++) | |
574 | { | |
575 | if (i > 0) | |
576 | put_decl_string (",", 1); | |
577 | put_decl_node (TREE_VALUE (args)); | |
578 | } | |
579 | put_decl_string (")", 1); | |
e04a16fb | 580 | } |
e04a16fb | 581 | } |
bc8a5e56 PB |
582 | else |
583 | put_decl_node (DECL_NAME (node)); | |
e04a16fb AG |
584 | } |
585 | else if (TREE_CODE_CLASS (TREE_CODE (node)) == 't' | |
586 | && TYPE_NAME (node) != NULL_TREE) | |
587 | { | |
588 | if (TREE_CODE (node) == RECORD_TYPE && TYPE_ARRAY_P (node)) | |
589 | { | |
590 | put_decl_node (TYPE_ARRAY_ELEMENT (node)); | |
591 | put_decl_string("[]", 2); | |
592 | } | |
593 | else if (node == promoted_byte_type_node) | |
594 | put_decl_string ("byte", 4); | |
595 | else if (node == promoted_short_type_node) | |
596 | put_decl_string ("short", 5); | |
597 | else if (node == promoted_char_type_node) | |
598 | put_decl_string ("char", 4); | |
599 | else if (node == promoted_boolean_type_node) | |
600 | put_decl_string ("boolean", 7); | |
601 | else if (node == void_type_node && was_pointer) | |
602 | put_decl_string ("null", 4); | |
603 | else | |
604 | put_decl_node (TYPE_NAME (node)); | |
605 | } | |
606 | else if (TREE_CODE (node) == IDENTIFIER_NODE) | |
607 | put_decl_string (IDENTIFIER_POINTER (node), IDENTIFIER_LENGTH (node)); | |
608 | else | |
609 | put_decl_string ("<unknown>", -1); | |
610 | } | |
611 | ||
612 | /* Return a user-friendly name for DECL. | |
613 | The resulting string is only valid until the next call. | |
614 | The value of the hook decl_printable_name is this function, | |
7cb32822 | 615 | which is also called directly by java_print_error_function. */ |
e04a16fb | 616 | |
1b93a502 | 617 | const char * |
0a2f0c54 | 618 | lang_printable_name (tree decl, int v __attribute__ ((__unused__))) |
e04a16fb AG |
619 | { |
620 | decl_bufpos = 0; | |
621 | put_decl_node (decl); | |
622 | put_decl_string ("", 1); | |
623 | return decl_buf; | |
624 | } | |
625 | ||
761491c8 APB |
626 | /* Does the same thing that lang_printable_name, but add a leading |
627 | space to the DECL name string -- With Leading Space. */ | |
628 | ||
629 | const char * | |
0a2f0c54 | 630 | lang_printable_name_wls (tree decl, int v __attribute__ ((__unused__))) |
761491c8 APB |
631 | { |
632 | decl_bufpos = 1; | |
633 | put_decl_node (decl); | |
634 | put_decl_string ("", 1); | |
635 | decl_buf [0] = ' '; | |
636 | return decl_buf; | |
637 | } | |
638 | ||
e04a16fb | 639 | /* Print on stderr the current class and method context. This function |
7cb32822 | 640 | is the value of the hook print_error_function. */ |
e04a16fb | 641 | |
e2500fed GK |
642 | static GTY(()) tree last_error_function_context; |
643 | static GTY(()) tree last_error_function; | |
be245ac0 | 644 | static void |
0a2f0c54 KG |
645 | java_print_error_function (diagnostic_context *context ATTRIBUTE_UNUSED, |
646 | const char *file) | |
e04a16fb | 647 | { |
7cb32822 NB |
648 | /* Don't print error messages with bogus function prototypes. */ |
649 | if (inhibit_error_function_printing) | |
650 | return; | |
651 | ||
e04a16fb AG |
652 | if (current_function_decl != NULL |
653 | && DECL_CONTEXT (current_function_decl) != last_error_function_context) | |
654 | { | |
655 | if (file) | |
656 | fprintf (stderr, "%s: ", file); | |
657 | ||
658 | last_error_function_context = DECL_CONTEXT (current_function_decl); | |
659 | fprintf (stderr, "In class `%s':\n", | |
0a2138e2 | 660 | lang_printable_name (last_error_function_context, 0)); |
e04a16fb AG |
661 | } |
662 | if (last_error_function != current_function_decl) | |
663 | { | |
664 | if (file) | |
665 | fprintf (stderr, "%s: ", file); | |
666 | ||
667 | if (current_function_decl == NULL) | |
668 | fprintf (stderr, "At top level:\n"); | |
669 | else | |
670 | { | |
c8e7d2e6 | 671 | const char *name = lang_printable_name (current_function_decl, 2); |
bc8a5e56 PB |
672 | fprintf (stderr, "In %s `%s':\n", |
673 | (DECL_CONSTRUCTOR_P (current_function_decl) ? "constructor" | |
674 | : "method"), | |
675 | name); | |
e04a16fb AG |
676 | } |
677 | ||
678 | last_error_function = current_function_decl; | |
679 | } | |
680 | ||
681 | } | |
682 | ||
e04a16fb AG |
683 | /* Called to install the PRINT_ERROR_FUNCTION hook differently |
684 | according to LEVEL. LEVEL is 1 during early parsing, when function | |
7cb32822 NB |
685 | prototypes aren't fully resolved. java_print_error_function is set |
686 | so it doesn't print incomplete function prototypes. When LEVEL is | |
687 | 2, function prototypes are fully resolved and can be printed when | |
e04a16fb AG |
688 | reporting errors. */ |
689 | ||
fe0b9fb5 RM |
690 | void |
691 | lang_init_source (int level) | |
e04a16fb | 692 | { |
7cb32822 | 693 | inhibit_error_function_printing = (level == 1); |
e04a16fb AG |
694 | } |
695 | ||
b86f6cd9 NB |
696 | static unsigned int |
697 | java_init_options (unsigned int argc ATTRIBUTE_UNUSED, | |
698 | const char **argv ATTRIBUTE_UNUSED) | |
e04a16fb | 699 | { |
13f9ac51 | 700 | flag_bounds_check = 1; |
da7da8f9 RH |
701 | flag_exceptions = 1; |
702 | flag_non_call_exceptions = 1; | |
f5eb5fd0 JH |
703 | |
704 | /* In Java floating point operations never trap. */ | |
705 | flag_trapping_math = 0; | |
4fa26a60 RS |
706 | |
707 | /* In Java arithmetic overflow always wraps around. */ | |
708 | flag_wrapv = 1; | |
2772ef3e | 709 | |
c67e6e14 RS |
710 | /* Java requires left-to-right evaluation of subexpressions. */ |
711 | flag_evaluation_order = 1; | |
712 | ||
95ca6d8b NB |
713 | jcf_path_init (); |
714 | ||
be43ab4e | 715 | return CL_Java; |
e04a16fb | 716 | } |
e2500fed | 717 | |
0d811e1a | 718 | static bool |
0a2f0c54 | 719 | java_can_use_bit_fields_p (void) |
0d811e1a TT |
720 | { |
721 | /* The bit-field optimizations cause problems when generating class | |
722 | files. */ | |
723 | return flag_emit_class_files ? false : true; | |
724 | } | |
725 | ||
36d010ca | 726 | /* Post-switch processing. */ |
5351f1ca | 727 | static bool |
4bfec483 | 728 | java_post_options (const char **pfilename) |
36d010ca | 729 | { |
4bfec483 NB |
730 | const char *filename = *pfilename; |
731 | ||
6de9cd9a DN |
732 | /* Use tree inlining. */ |
733 | if (!flag_no_inline) | |
734 | flag_no_inline = 1; | |
735 | if (flag_inline_functions) | |
36d010ca | 736 | { |
6de9cd9a DN |
737 | flag_inline_trees = 2; |
738 | flag_inline_functions = 0; | |
36d010ca | 739 | } |
5351f1ca | 740 | |
4bfec483 NB |
741 | /* Open input file. */ |
742 | ||
743 | if (filename == 0 || !strcmp (filename, "-")) | |
744 | { | |
745 | finput = stdin; | |
746 | filename = "stdin"; | |
747 | ||
748 | if (dependency_tracking) | |
749 | error ("can't do dependency tracking with input from stdin"); | |
750 | } | |
751 | else | |
752 | { | |
753 | if (dependency_tracking) | |
754 | { | |
755 | char *dot; | |
756 | ||
757 | /* If the target is set and the output filename is set, then | |
758 | there's no processing to do here. Otherwise we must | |
759 | compute one or the other. */ | |
760 | if (! ((dependency_tracking & DEPEND_TARGET_SET) | |
761 | && (dependency_tracking & DEPEND_FILE_ALREADY_SET))) | |
762 | { | |
763 | dot = strrchr (filename, '.'); | |
764 | if (dot == NULL) | |
765 | error ("couldn't determine target name for dependency tracking"); | |
766 | else | |
767 | { | |
768 | char *buf = xmalloc (dot - filename + | |
769 | 3 + sizeof (TARGET_OBJECT_SUFFIX)); | |
770 | strncpy (buf, filename, dot - filename); | |
771 | ||
772 | /* If emitting class files, we might have multiple | |
773 | targets. The class generation code takes care of | |
774 | registering them. Otherwise we compute the | |
775 | target name here. */ | |
776 | if ((dependency_tracking & DEPEND_TARGET_SET)) | |
777 | ; /* Nothing. */ | |
778 | else if (flag_emit_class_files) | |
779 | jcf_dependency_set_target (NULL); | |
780 | else | |
781 | { | |
782 | strcpy (buf + (dot - filename), TARGET_OBJECT_SUFFIX); | |
783 | jcf_dependency_set_target (buf); | |
784 | } | |
785 | ||
786 | if ((dependency_tracking & DEPEND_FILE_ALREADY_SET)) | |
787 | ; /* Nothing. */ | |
788 | else if ((dependency_tracking & DEPEND_SET_FILE)) | |
789 | { | |
790 | strcpy (buf + (dot - filename), ".d"); | |
791 | jcf_dependency_set_dep_file (buf); | |
792 | } | |
793 | else | |
794 | jcf_dependency_set_dep_file ("-"); | |
795 | ||
796 | free (buf); | |
797 | } | |
798 | } | |
799 | } | |
800 | } | |
801 | ||
5351f1ca NB |
802 | /* Initialize the compiler back end. */ |
803 | return false; | |
36d010ca BM |
804 | } |
805 | ||
7149627b AH |
806 | /* Return either DECL or its known constant value (if it has one). */ |
807 | ||
808 | tree | |
0a2f0c54 | 809 | decl_constant_value (tree decl) |
7149627b AH |
810 | { |
811 | if (/* Don't change a variable array bound or initial value to a constant | |
812 | in a place where a variable is invalid. */ | |
813 | current_function_decl != 0 | |
814 | && ! TREE_THIS_VOLATILE (decl) | |
815 | && TREE_READONLY (decl) | |
816 | && DECL_INITIAL (decl) != 0 | |
817 | && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK | |
818 | /* This is invalid if initial value is not constant. | |
819 | If it has either a function call, a memory reference, | |
820 | or a variable, then re-evaluating it could give different results. */ | |
821 | && TREE_CONSTANT (DECL_INITIAL (decl)) | |
822 | /* Check for cases where this is sub-optimal, even though valid. */ | |
823 | && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR) | |
824 | return DECL_INITIAL (decl); | |
825 | return decl; | |
826 | } | |
827 | ||
828 | /* Walk the language specific tree nodes during inlining. */ | |
829 | ||
830 | static tree | |
0a2f0c54 KG |
831 | java_tree_inlining_walk_subtrees (tree *tp ATTRIBUTE_UNUSED, |
832 | int *subtrees ATTRIBUTE_UNUSED, | |
833 | walk_tree_fn func ATTRIBUTE_UNUSED, | |
834 | void *data ATTRIBUTE_UNUSED, | |
835 | void *htab ATTRIBUTE_UNUSED) | |
7149627b AH |
836 | { |
837 | enum tree_code code; | |
838 | tree result; | |
839 | ||
840 | #define WALK_SUBTREE(NODE) \ | |
841 | do \ | |
842 | { \ | |
843 | result = walk_tree (&(NODE), func, data, htab); \ | |
844 | if (result) \ | |
845 | return result; \ | |
846 | } \ | |
847 | while (0) | |
848 | ||
849 | tree t = *tp; | |
850 | if (!t) | |
851 | return NULL_TREE; | |
852 | ||
853 | code = TREE_CODE (t); | |
854 | switch (code) | |
855 | { | |
856 | case BLOCK: | |
1b2b8ee7 | 857 | WALK_SUBTREE (BLOCK_EXPR_BODY (t)); |
7149627b | 858 | return NULL_TREE; |
7149627b AH |
859 | |
860 | default: | |
861 | return NULL_TREE; | |
862 | } | |
1b2b8ee7 JM |
863 | |
864 | #undef WALK_SUBTREE | |
7149627b AH |
865 | } |
866 | ||
8943a0b4 RH |
867 | /* Called from unsafe_for_reeval. */ |
868 | static int | |
0a2f0c54 | 869 | java_unsafe_for_reeval (tree t) |
8943a0b4 RH |
870 | { |
871 | switch (TREE_CODE (t)) | |
872 | { | |
873 | case BLOCK: | |
874 | /* Our expander tries to expand the variables twice. Boom. */ | |
875 | if (BLOCK_EXPR_DECLS (t) != NULL) | |
876 | return 2; | |
877 | return unsafe_for_reeval (BLOCK_EXPR_BODY (t)); | |
878 | ||
879 | default: | |
880 | break; | |
881 | } | |
882 | ||
883 | return -1; | |
884 | } | |
885 | ||
3eb429b2 AH |
886 | /* Every call to a static constructor has an associated boolean |
887 | variable which is in the outermost scope of the calling method. | |
888 | This variable is used to avoid multiple calls to the static | |
889 | constructor for each class. | |
890 | ||
634661fe | 891 | It looks something like this: |
3eb429b2 AH |
892 | |
893 | foo () | |
894 | { | |
895 | boolean dummy = OtherClass.is_initialized; | |
896 | ||
897 | ... | |
898 | ||
899 | if (! dummy) | |
900 | OtherClass.initialize(); | |
901 | ||
902 | ... use OtherClass.data ... | |
903 | } | |
904 | ||
905 | Each of these boolean variables has an entry in the | |
906 | DECL_FUNCTION_INIT_TEST_TABLE of a method. When inlining a method | |
907 | we must merge the DECL_FUNCTION_INIT_TEST_TABLE from the function | |
634661fe | 908 | being inlined and create the boolean variables in the outermost |
3eb429b2 AH |
909 | scope of the method being inlined into. */ |
910 | ||
911 | /* Create a mapping from a boolean variable in a method being inlined | |
912 | to one in the scope of the method being inlined into. */ | |
913 | ||
914 | static int | |
0a2f0c54 | 915 | merge_init_test_initialization (void **entry, void *x) |
3eb429b2 AH |
916 | { |
917 | struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry; | |
918 | splay_tree decl_map = (splay_tree)x; | |
919 | splay_tree_node n; | |
920 | tree *init_test_decl; | |
921 | ||
922 | /* See if we have remapped this declaration. If we haven't there's | |
923 | a bug in the inliner. */ | |
924 | n = splay_tree_lookup (decl_map, (splay_tree_key) ite->value); | |
925 | if (! n) | |
926 | abort (); | |
927 | ||
928 | /* Create a new entry for the class and its remapped boolean | |
929 | variable. If we already have a mapping for this class we've | |
930 | already initialized it, so don't overwrite the value. */ | |
931 | init_test_decl = java_treetreehash_new | |
932 | (DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), ite->key); | |
933 | if (!*init_test_decl) | |
934 | *init_test_decl = (tree)n->value; | |
935 | ||
7304c6cf AH |
936 | /* This fixes a weird case. |
937 | ||
938 | The front end assumes that once we have called a method that | |
939 | initializes some class, we can assume the class is initialized. It | |
940 | does this by setting the DECL_INITIAL of the init_test_decl for that | |
941 | class, and no initializations are emitted for that class. | |
942 | ||
943 | However, what if the method that is suppoed to do the initialization | |
944 | is itself inlined in the caller? When expanding the called method | |
c048d56d | 945 | we'll assume that the class initialization has already been done, |
7304c6cf AH |
946 | because the DECL_INITIAL of the init_test_decl is set. |
947 | ||
948 | To fix this we remove the DECL_INITIAL (in the caller scope) of all | |
949 | the init_test_decls corresponding to classes initialized by the | |
950 | inlined method. This makes the caller no longer assume that the | |
951 | method being inlined does any class initializations. */ | |
952 | DECL_INITIAL (*init_test_decl) = NULL; | |
953 | ||
3eb429b2 AH |
954 | return true; |
955 | } | |
956 | ||
957 | /* Merge the DECL_FUNCTION_INIT_TEST_TABLE from the function we're | |
958 | inlining. */ | |
959 | ||
960 | void | |
0a2f0c54 | 961 | java_inlining_merge_static_initializers (tree fn, void *decl_map) |
3eb429b2 AH |
962 | { |
963 | htab_traverse | |
964 | (DECL_FUNCTION_INIT_TEST_TABLE (fn), | |
965 | merge_init_test_initialization, decl_map); | |
966 | } | |
967 | ||
968 | /* Lookup a DECL_FUNCTION_INIT_TEST_TABLE entry in the method we're | |
969 | inlining into. If we already have a corresponding entry in that | |
970 | class we don't need to create another one, so we create a mapping | |
971 | from the variable in the inlined class to the corresponding | |
972 | pre-existing one. */ | |
973 | ||
974 | static int | |
0a2f0c54 | 975 | inline_init_test_initialization (void **entry, void *x) |
3eb429b2 AH |
976 | { |
977 | struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry; | |
978 | splay_tree decl_map = (splay_tree)x; | |
979 | ||
980 | tree h = java_treetreehash_find | |
981 | (DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), ite->key); | |
982 | if (! h) | |
983 | return true; | |
3eb429b2 AH |
984 | splay_tree_insert (decl_map, |
985 | (splay_tree_key) ite->value, | |
986 | (splay_tree_value) h); | |
3eb429b2 AH |
987 | return true; |
988 | } | |
989 | ||
990 | /* Look up the boolean variables in the DECL_FUNCTION_INIT_TEST_TABLE | |
991 | of a method being inlined. For each hone, if we already have a | |
992 | variable associated with the same class in the method being inlined | |
993 | into, create a new mapping for it. */ | |
994 | ||
995 | void | |
0a2f0c54 | 996 | java_inlining_map_static_initializers (tree fn, void *decl_map) |
3eb429b2 AH |
997 | { |
998 | htab_traverse | |
999 | (DECL_FUNCTION_INIT_TEST_TABLE (fn), | |
1000 | inline_init_test_initialization, decl_map); | |
1001 | } | |
1002 | ||
c1ddb5c8 AH |
1003 | /* Avoid voluminous output for deep recursion of compound exprs. */ |
1004 | ||
1005 | static void | |
0a2f0c54 | 1006 | dump_compound_expr (dump_info_p di, tree t) |
c1ddb5c8 AH |
1007 | { |
1008 | int i; | |
1009 | ||
1010 | for (i=0; i<2; i++) | |
1011 | { | |
1012 | switch (TREE_CODE (TREE_OPERAND (t, i))) | |
1013 | { | |
1014 | case COMPOUND_EXPR: | |
1015 | dump_compound_expr (di, TREE_OPERAND (t, i)); | |
1016 | break; | |
1017 | ||
1018 | case EXPR_WITH_FILE_LOCATION: | |
1019 | { | |
1020 | tree wfl_node = EXPR_WFL_NODE (TREE_OPERAND (t, i)); | |
1021 | dump_child ("expr", wfl_node); | |
1022 | break; | |
1023 | } | |
1024 | ||
1025 | default: | |
1026 | dump_child ("expr", TREE_OPERAND (t, i)); | |
1027 | } | |
1028 | } | |
1029 | } | |
1030 | ||
2bd3ecad | 1031 | static bool |
0a2f0c54 | 1032 | java_dump_tree (void *dump_info, tree t) |
c1ddb5c8 AH |
1033 | { |
1034 | enum tree_code code; | |
1035 | dump_info_p di = (dump_info_p) dump_info; | |
1036 | ||
1037 | /* Figure out what kind of node this is. */ | |
1038 | code = TREE_CODE (t); | |
1039 | ||
1040 | switch (code) | |
1041 | { | |
1042 | case FUNCTION_DECL: | |
1043 | dump_child ("args", DECL_ARGUMENTS (t)); | |
1044 | if (DECL_EXTERNAL (t)) | |
1045 | dump_string (di, "undefined"); | |
1046 | if (TREE_PUBLIC (t)) | |
1047 | dump_string (di, "extern"); | |
1048 | else | |
1049 | dump_string (di, "static"); | |
1050 | if (DECL_LANG_SPECIFIC (t)) | |
1051 | dump_child ("body", DECL_FUNCTION_BODY (t)); | |
1052 | if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t)) | |
1053 | dump_child ("inline body", DECL_SAVED_TREE (t)); | |
2bd3ecad | 1054 | return true; |
c1ddb5c8 AH |
1055 | |
1056 | case RETURN_EXPR: | |
1057 | dump_child ("expr", TREE_OPERAND (t, 0)); | |
2bd3ecad | 1058 | return true; |
c1ddb5c8 AH |
1059 | |
1060 | case GOTO_EXPR: | |
1061 | dump_child ("goto", TREE_OPERAND (t, 0)); | |
2bd3ecad | 1062 | return true; |
c1ddb5c8 AH |
1063 | |
1064 | case LABEL_EXPR: | |
1065 | dump_child ("label", TREE_OPERAND (t, 0)); | |
2bd3ecad | 1066 | return true; |
c1ddb5c8 AH |
1067 | |
1068 | case LABELED_BLOCK_EXPR: | |
1069 | dump_child ("label", TREE_OPERAND (t, 0)); | |
1070 | dump_child ("block", TREE_OPERAND (t, 1)); | |
2bd3ecad | 1071 | return true; |
c1ddb5c8 AH |
1072 | |
1073 | case EXIT_BLOCK_EXPR: | |
1074 | dump_child ("block", TREE_OPERAND (t, 0)); | |
1075 | dump_child ("val", TREE_OPERAND (t, 1)); | |
2bd3ecad | 1076 | return true; |
c1ddb5c8 AH |
1077 | |
1078 | case BLOCK: | |
1079 | if (BLOCK_EXPR_BODY (t)) | |
1080 | { | |
1081 | tree local = BLOCK_VARS (t); | |
1082 | while (local) | |
1083 | { | |
1084 | tree next = TREE_CHAIN (local); | |
1085 | dump_child ("var", local); | |
1086 | local = next; | |
1087 | } | |
1088 | ||
1089 | { | |
1090 | tree block = BLOCK_EXPR_BODY (t); | |
1091 | dump_child ("body", block); | |
1092 | block = TREE_CHAIN (block); | |
1093 | } | |
1094 | } | |
2bd3ecad | 1095 | return true; |
c1ddb5c8 AH |
1096 | |
1097 | case COMPOUND_EXPR: | |
1098 | if (!dump_flag (di, TDF_SLIM, t)) | |
2bd3ecad | 1099 | return false; |
c1ddb5c8 | 1100 | dump_compound_expr (di, t); |
2bd3ecad | 1101 | return true; |
c1ddb5c8 AH |
1102 | |
1103 | default: | |
1104 | break; | |
1105 | } | |
2bd3ecad | 1106 | return false; |
c1ddb5c8 | 1107 | } |
e076f71a AH |
1108 | |
1109 | /* Java calls can't, in general, be sibcalls because we need an | |
1110 | accurate stack trace in order to guarantee correct operation of | |
1111 | methods such as Class.forName(String) and | |
1112 | SecurityManager.getClassContext(). */ | |
1113 | ||
1114 | static bool | |
1115 | java_decl_ok_for_sibcall (tree decl) | |
1116 | { | |
85194ee9 | 1117 | return decl != NULL && DECL_CONTEXT (decl) == output_class; |
e076f71a AH |
1118 | } |
1119 | ||
90471585 AH |
1120 | /* Given a call_expr, try to figure out what its target might be. In |
1121 | the case of an indirection via the atable, search for the decl. If | |
1122 | the decl is external, we return NULL. If we don't, the optimizer | |
1123 | will replace the indirection with a direct call, which undoes the | |
1124 | purpose of the atable indirection. */ | |
1125 | static tree | |
1126 | java_get_callee_fndecl (tree call_expr) | |
1127 | { | |
85194ee9 | 1128 | tree method, table, element, atable_methods; |
90471585 AH |
1129 | |
1130 | HOST_WIDE_INT index; | |
1131 | ||
1132 | if (TREE_CODE (call_expr) != CALL_EXPR) | |
1133 | return NULL; | |
1134 | method = TREE_OPERAND (call_expr, 0); | |
1135 | STRIP_NOPS (method); | |
1136 | if (TREE_CODE (method) != ARRAY_REF) | |
1137 | return NULL; | |
1138 | table = TREE_OPERAND (method, 0); | |
85194ee9 AH |
1139 | if (! DECL_LANG_SPECIFIC(table) |
1140 | || !DECL_OWNER (table) | |
1141 | || TYPE_ATABLE_DECL (DECL_OWNER (table)) != table) | |
90471585 | 1142 | return NULL; |
90471585 | 1143 | |
85194ee9 AH |
1144 | atable_methods = TYPE_ATABLE_METHODS (DECL_OWNER (table)); |
1145 | index = TREE_INT_CST_LOW (TREE_OPERAND (method, 1)); | |
1146 | ||
90471585 AH |
1147 | /* FIXME: Replace this for loop with a hash table lookup. */ |
1148 | for (element = atable_methods; element; element = TREE_CHAIN (element)) | |
1149 | { | |
1150 | if (index == 1) | |
1151 | { | |
1152 | tree purpose = TREE_PURPOSE (element); | |
1153 | if (TREE_CODE (purpose) == FUNCTION_DECL | |
1154 | && ! DECL_EXTERNAL (purpose)) | |
1155 | return purpose; | |
1156 | else | |
1157 | return NULL; | |
1158 | } | |
1159 | --index; | |
1160 | } | |
85194ee9 | 1161 | |
90471585 AH |
1162 | return NULL; |
1163 | } | |
1164 | ||
e2500fed | 1165 | #include "gt-java-lang.h" |