]>
Commit | Line | Data |
---|---|---|
377029eb | 1 | /* Java(TM) language-specific utility routines. |
65bf3316 | 2 | Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, |
8faccfb9 | 3 | 2005, 2006, 2007, 2008, 2010 Free Software Foundation, Inc. |
377029eb | 4 | |
7d82ed5e | 5 | This file is part of GCC. |
377029eb | 6 | |
7d82ed5e | 7 | GCC is free software; you can redistribute it and/or modify |
377029eb | 8 | it under the terms of the GNU General Public License as published by |
e4b52719 | 9 | the Free Software Foundation; either version 3, or (at your option) |
377029eb | 10 | any later version. |
11 | ||
7d82ed5e | 12 | GCC is distributed in the hope that it will be useful, |
377029eb | 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
e4b52719 | 18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. | |
377029eb | 20 | |
21 | Java and all Java-based marks are trademarks or registered trademarks | |
22 | of Sun Microsystems, Inc. in the United States and other countries. | |
23 | The Free Software Foundation is independent of Sun Microsystems, Inc. */ | |
24 | ||
25 | /* Hacked by Per Bothner <bothner@cygnus.com> February 1996. */ | |
26 | ||
377029eb | 27 | #include "config.h" |
014e6e0c | 28 | #include "system.h" |
805e22b2 | 29 | #include "coretypes.h" |
30 | #include "tm.h" | |
377029eb | 31 | #include "tree.h" |
32 | #include "input.h" | |
33 | #include "java-tree.h" | |
34 | #include "jcf.h" | |
014e6e0c | 35 | #include "toplev.h" |
d1c00d75 | 36 | #include "langhooks.h" |
b0278d39 | 37 | #include "langhooks-def.h" |
b76c045f | 38 | #include "flags.h" |
48c9f822 | 39 | #include "ggc.h" |
b506dc01 | 40 | #include "diagnostic.h" |
53d20e65 | 41 | #include "tree-inline.h" |
16ceebae | 42 | #include "splay-tree.h" |
03e05510 | 43 | #include "tree-dump.h" |
b3db0901 | 44 | #include "opts.h" |
3272db82 | 45 | #include "options.h" |
01ce8ed3 | 46 | |
03bde601 | 47 | static bool java_init (void); |
6852521a | 48 | static void java_finish (void); |
4838a8b6 | 49 | static unsigned int java_init_options (unsigned int, const char **); |
03bde601 | 50 | static bool java_post_options (const char **); |
08cb25b3 | 51 | |
1f3db819 | 52 | static int java_handle_option (size_t scode, const char *arg, int value, int kind); |
6852521a | 53 | static void put_decl_string (const char *, int); |
6bbcd977 | 54 | static void put_decl_node (tree, int); |
b8c23db3 | 55 | static void java_print_error_function (diagnostic_context *, const char *, |
56 | diagnostic_info *); | |
6852521a | 57 | static int merge_init_test_initialization (void * *, void *); |
58 | static int inline_init_test_initialization (void * *, void *); | |
fb84380a | 59 | static bool java_dump_tree (void *, tree); |
6852521a | 60 | static void dump_compound_expr (dump_info_p, tree); |
9f627b1a | 61 | static bool java_decl_ok_for_sibcall (const_tree); |
8531f242 | 62 | |
03a61d93 | 63 | static enum classify_record java_classify_record (tree type); |
64 | ||
58d82cd0 | 65 | static tree java_eh_personality (void); |
66 | ||
10f57222 | 67 | #ifndef TARGET_OBJECT_SUFFIX |
68 | # define TARGET_OBJECT_SUFFIX ".o" | |
bb9b756c | 69 | #endif |
70 | ||
7e6a29a6 | 71 | /* Table of machine-independent attributes. */ |
72 | const struct attribute_spec java_attribute_table[] = | |
73 | { | |
74 | { "nonnull", 0, -1, false, true, true, | |
75 | NULL }, | |
76 | { NULL, 0, 0, false, false, false, NULL } | |
77 | }; | |
78 | ||
6c7ff025 | 79 | /* Used to avoid printing error messages with bogus function |
80 | prototypes. Starts out false. */ | |
81 | static bool inhibit_error_function_printing; | |
82 | ||
35171f45 | 83 | const char *resource_name; |
7ad6876a | 84 | |
86523f9c | 85 | /* When nonzero, -Wall was turned on. */ |
6b0c8920 | 86 | int flag_wall = 0; |
87 | ||
a4ccc41f | 88 | /* When nonzero, report use of deprecated classes, methods, or fields. */ |
89 | int flag_deprecated = 1; | |
90 | ||
91 | /* When zero, don't optimize static class initialization. This flag shouldn't | |
92 | be tested alone, use STATIC_CLASS_INITIALIZATION_OPTIMIZATION_P instead. */ | |
93 | /* FIXME: Make this work with gimplify. */ | |
94 | /* int flag_optimize_sci = 0; */ | |
95 | ||
96 | /* Don't attempt to verify invocations. */ | |
97 | int flag_verify_invocations = 0; | |
98 | ||
86523f9c | 99 | /* When nonzero, print extra version information. */ |
e690b385 | 100 | static int v_flag = 0; |
37d9d338 | 101 | |
377029eb | 102 | JCF *current_jcf; |
103 | ||
b76c045f | 104 | /* Variable controlling how dependency tracking is enabled in |
9ceb1c29 | 105 | java_init. */ |
b76c045f | 106 | static int dependency_tracking = 0; |
107 | ||
108 | /* Flag values for DEPENDENCY_TRACKING. */ | |
109 | #define DEPEND_SET_FILE 1 | |
110 | #define DEPEND_ENABLE 2 | |
fecb951e | 111 | #define DEPEND_TARGET_SET 4 |
112 | #define DEPEND_FILE_ALREADY_SET 8 | |
b76c045f | 113 | |
fb1e4f4a | 114 | struct GTY(()) language_function { |
1f3233d1 | 115 | int unused; |
116 | }; | |
117 | ||
d19bd1f0 | 118 | #undef LANG_HOOKS_NAME |
119 | #define LANG_HOOKS_NAME "GNU Java" | |
d1c00d75 | 120 | #undef LANG_HOOKS_INIT |
121 | #define LANG_HOOKS_INIT java_init | |
cdc9fa3e | 122 | #undef LANG_HOOKS_FINISH |
123 | #define LANG_HOOKS_FINISH java_finish | |
d1c00d75 | 124 | #undef LANG_HOOKS_INIT_OPTIONS |
125 | #define LANG_HOOKS_INIT_OPTIONS java_init_options | |
35171f45 | 126 | #undef LANG_HOOKS_HANDLE_OPTION |
127 | #define LANG_HOOKS_HANDLE_OPTION java_handle_option | |
08cb25b3 | 128 | #undef LANG_HOOKS_POST_OPTIONS |
129 | #define LANG_HOOKS_POST_OPTIONS java_post_options | |
b78207a0 | 130 | #undef LANG_HOOKS_PARSE_FILE |
131 | #define LANG_HOOKS_PARSE_FILE java_parse_file | |
dbc42b78 | 132 | #undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL |
133 | #define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL java_dup_lang_specific_decl | |
96554925 | 134 | #undef LANG_HOOKS_DECL_PRINTABLE_NAME |
135 | #define LANG_HOOKS_DECL_PRINTABLE_NAME lang_printable_name | |
6c7ff025 | 136 | #undef LANG_HOOKS_PRINT_ERROR_FUNCTION |
137 | #define LANG_HOOKS_PRINT_ERROR_FUNCTION java_print_error_function | |
8faccfb9 | 138 | #undef LANG_HOOKS_WRITE_GLOBALS |
139 | #define LANG_HOOKS_WRITE_GLOBALS java_write_globals | |
4070745f | 140 | |
771d21fa | 141 | #undef LANG_HOOKS_TYPE_FOR_MODE |
142 | #define LANG_HOOKS_TYPE_FOR_MODE java_type_for_mode | |
143 | #undef LANG_HOOKS_TYPE_FOR_SIZE | |
144 | #define LANG_HOOKS_TYPE_FOR_SIZE java_type_for_size | |
03a61d93 | 145 | #undef LANG_HOOKS_CLASSIFY_RECORD |
146 | #define LANG_HOOKS_CLASSIFY_RECORD java_classify_record | |
d1c00d75 | 147 | |
03e05510 | 148 | #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN |
149 | #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN java_dump_tree | |
150 | ||
4ee9c684 | 151 | #undef LANG_HOOKS_GIMPLIFY_EXPR |
152 | #define LANG_HOOKS_GIMPLIFY_EXPR java_gimplify_expr | |
153 | ||
e2e9c55b | 154 | #undef LANG_HOOKS_DECL_OK_FOR_SIBCALL |
155 | #define LANG_HOOKS_DECL_OK_FOR_SIBCALL java_decl_ok_for_sibcall | |
156 | ||
dc5e5216 | 157 | #undef LANG_HOOKS_SET_DECL_ASSEMBLER_NAME |
158 | #define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME java_mangle_decl | |
159 | ||
7e6a29a6 | 160 | #undef LANG_HOOKS_ATTRIBUTE_TABLE |
161 | #define LANG_HOOKS_ATTRIBUTE_TABLE java_attribute_table | |
162 | ||
58d82cd0 | 163 | #undef LANG_HOOKS_EH_PERSONALITY |
164 | #define LANG_HOOKS_EH_PERSONALITY java_eh_personality | |
165 | ||
471eff36 | 166 | #undef LANG_HOOKS_EH_USE_CXA_END_CLEANUP |
167 | #define LANG_HOOKS_EH_USE_CXA_END_CLEANUP true | |
168 | ||
50c7fc99 | 169 | /* Each front end provides its own. */ |
34e5cced | 170 | struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; |
50c7fc99 | 171 | |
377029eb | 172 | /* |
173 | * process java-specific compiler command-line options | |
92839031 | 174 | * return 0, but do not complain if the option is not recognized. |
377029eb | 175 | */ |
e486a835 | 176 | static int |
1f3db819 | 177 | java_handle_option (size_t scode, const char *arg, int value, |
178 | int kind ATTRIBUTE_UNUSED) | |
377029eb | 179 | { |
35171f45 | 180 | enum opt_code code = (enum opt_code) scode; |
e8ca16d1 | 181 | |
35171f45 | 182 | switch (code) |
377029eb | 183 | { |
35171f45 | 184 | case OPT_I: |
185 | jcf_path_include_arg (arg); | |
186 | break; | |
491906d3 | 187 | |
35171f45 | 188 | case OPT_M: |
189 | jcf_dependency_init (1); | |
190 | dependency_tracking |= DEPEND_ENABLE; | |
191 | break; | |
16792571 | 192 | |
41e04369 | 193 | case OPT_MD_: |
b76c045f | 194 | jcf_dependency_init (1); |
195 | dependency_tracking |= DEPEND_SET_FILE | DEPEND_ENABLE; | |
35171f45 | 196 | break; |
197 | ||
198 | case OPT_MF: | |
199 | jcf_dependency_set_dep_file (arg); | |
4c8e932f | 200 | dependency_tracking |= DEPEND_FILE_ALREADY_SET; |
35171f45 | 201 | break; |
202 | ||
203 | case OPT_MM: | |
b76c045f | 204 | jcf_dependency_init (0); |
b76c045f | 205 | dependency_tracking |= DEPEND_ENABLE; |
35171f45 | 206 | break; |
207 | ||
41e04369 | 208 | case OPT_MMD_: |
b76c045f | 209 | jcf_dependency_init (0); |
35171f45 | 210 | dependency_tracking |= DEPEND_SET_FILE | DEPEND_ENABLE; |
211 | break; | |
212 | ||
213 | case OPT_MP: | |
fecb951e | 214 | jcf_dependency_print_dummies (); |
35171f45 | 215 | break; |
216 | ||
217 | case OPT_MT: | |
218 | jcf_dependency_set_target (arg); | |
fecb951e | 219 | dependency_tracking |= DEPEND_TARGET_SET; |
35171f45 | 220 | break; |
b76c045f | 221 | |
35171f45 | 222 | case OPT_Wall: |
223 | flag_wall = value; | |
35171f45 | 224 | /* When -Wall given, enable -Wunused. We do this because the C |
225 | compiler does it, and people expect it. */ | |
278e3a1f | 226 | warn_unused = value; |
35171f45 | 227 | break; |
228 | ||
8dd2deb1 | 229 | case OPT_fenable_assertions_: |
230 | add_enable_assert (arg, value); | |
231 | break; | |
232 | ||
233 | case OPT_fenable_assertions: | |
234 | add_enable_assert ("", value); | |
235 | break; | |
236 | ||
237 | case OPT_fdisable_assertions_: | |
238 | add_enable_assert (arg, !value); | |
239 | break; | |
240 | ||
241 | case OPT_fdisable_assertions: | |
242 | add_enable_assert ("", !value); | |
243 | break; | |
244 | ||
35171f45 | 245 | case OPT_fassume_compiled_: |
246 | add_assume_compiled (arg, !value); | |
247 | break; | |
248 | ||
249 | case OPT_fassume_compiled: | |
250 | add_assume_compiled ("", !value); | |
251 | break; | |
252 | ||
253 | case OPT_fbootclasspath_: | |
254 | jcf_path_bootclasspath_arg (arg); | |
255 | break; | |
256 | ||
65bf3316 | 257 | case OPT_faux_classpath: |
35171f45 | 258 | case OPT_fclasspath_: |
259 | case OPT_fCLASSPATH_: | |
260 | jcf_path_classpath_arg (arg); | |
261 | break; | |
262 | ||
263 | case OPT_fcompile_resource_: | |
264 | resource_name = arg; | |
265 | break; | |
266 | ||
267 | case OPT_fdump_: | |
ffbc8512 | 268 | if (!dump_switch_p (arg)) |
468fe957 | 269 | return 0; |
35171f45 | 270 | break; |
271 | ||
35171f45 | 272 | case OPT_fencoding_: |
65bf3316 | 273 | /* Nothing. */ |
35171f45 | 274 | break; |
275 | ||
276 | case OPT_fextdirs_: | |
277 | jcf_path_extdirs_arg (arg); | |
278 | break; | |
279 | ||
35171f45 | 280 | case OPT_foutput_class_dir_: |
65bf3316 | 281 | /* FIXME: remove; this is handled by ecj1 now. */ |
35171f45 | 282 | break; |
283 | ||
35171f45 | 284 | case OPT_version: |
e690b385 | 285 | v_flag = 1; |
35171f45 | 286 | break; |
9be27950 | 287 | |
65bf3316 | 288 | case OPT_fsource_filename_: |
289 | java_read_sourcefilenames (arg); | |
290 | break; | |
291 | ||
9be27950 | 292 | default: |
293 | if (cl_options[code].flags & CL_Java) | |
294 | break; | |
bc031ffe | 295 | gcc_unreachable (); |
35171f45 | 296 | } |
297 | ||
298 | return 1; | |
377029eb | 299 | } |
300 | ||
f1afe160 | 301 | /* Global open file. */ |
377029eb | 302 | FILE *finput; |
f1afe160 | 303 | |
03bde601 | 304 | static bool |
305 | java_init (void) | |
377029eb | 306 | { |
757f6c6c | 307 | /* FIXME: Indirect dispatch isn't yet compatible with static class |
308 | init optimization. */ | |
309 | if (flag_indirect_dispatch) | |
310 | always_initialize_class_p = true; | |
311 | ||
2934c6b5 | 312 | if (!flag_indirect_dispatch) |
313 | flag_indirect_classes = false; | |
314 | ||
e690b385 | 315 | jcf_path_seal (v_flag); |
9ceb1c29 | 316 | |
9ceb1c29 | 317 | java_init_decl_processing (); |
318 | ||
319 | using_eh_for_cleanups (); | |
320 | ||
03bde601 | 321 | return true; |
377029eb | 322 | } |
323 | ||
cdc9fa3e | 324 | static void |
2883a3ed | 325 | java_finish (void) |
377029eb | 326 | { |
b76c045f | 327 | jcf_dependency_write (); |
377029eb | 328 | } |
329 | ||
330 | /* Buffer used by lang_printable_name. */ | |
331 | static char *decl_buf = NULL; | |
332 | ||
333 | /* Allocated size of decl_buf. */ | |
334 | static int decl_buflen = 0; | |
335 | ||
336 | /* Length of used part of decl_buf; position for next character. */ | |
337 | static int decl_bufpos = 0; | |
338 | ||
339 | /* Append the string STR to decl_buf. | |
340 | It length is given by LEN; -1 means the string is nul-terminated. */ | |
341 | ||
342 | static void | |
2883a3ed | 343 | put_decl_string (const char *str, int len) |
377029eb | 344 | { |
345 | if (len < 0) | |
346 | len = strlen (str); | |
347 | if (decl_bufpos + len >= decl_buflen) | |
348 | { | |
349 | if (decl_buf == NULL) | |
350 | { | |
351 | decl_buflen = len + 100; | |
4c36ffe6 | 352 | decl_buf = XNEWVEC (char, decl_buflen); |
377029eb | 353 | } |
354 | else | |
355 | { | |
356 | decl_buflen *= 2; | |
25a1c410 | 357 | decl_buf = XRESIZEVAR (char, decl_buf, decl_buflen); |
377029eb | 358 | } |
359 | } | |
360 | strcpy (decl_buf + decl_bufpos, str); | |
361 | decl_bufpos += len; | |
362 | } | |
363 | ||
6bbcd977 | 364 | /* Append to decl_buf a printable name for NODE. |
365 | Depending on VERBOSITY, more information about NODE | |
366 | is printed. Read the comments of decl_printable_name in | |
367 | langhooks.h for more. */ | |
377029eb | 368 | |
369 | static void | |
6bbcd977 | 370 | put_decl_node (tree node, int verbosity) |
377029eb | 371 | { |
372 | int was_pointer = 0; | |
373 | if (TREE_CODE (node) == POINTER_TYPE) | |
374 | { | |
375 | node = TREE_TYPE (node); | |
376 | was_pointer = 1; | |
377 | } | |
ce45a448 | 378 | if (DECL_P (node) && DECL_NAME (node) != NULL_TREE) |
377029eb | 379 | { |
9fb34998 | 380 | if (TREE_CODE (node) == FUNCTION_DECL) |
112ff39a | 381 | { |
6bbcd977 | 382 | if (verbosity == 0 && DECL_NAME (node)) |
383 | /* We have been instructed to just print the bare name | |
384 | of the function. */ | |
385 | { | |
386 | put_decl_node (DECL_NAME (node), 0); | |
387 | return; | |
388 | } | |
389 | ||
9fb34998 | 390 | /* We want to print the type the DECL belongs to. We don't do |
391 | that when we handle constructors. */ | |
392 | if (! DECL_CONSTRUCTOR_P (node) | |
6bbcd977 | 393 | && ! DECL_ARTIFICIAL (node) && DECL_CONTEXT (node) |
394 | /* We want to print qualified DECL names only | |
395 | if verbosity is higher than 1. */ | |
396 | && verbosity >= 1) | |
377029eb | 397 | { |
6bbcd977 | 398 | put_decl_node (TYPE_NAME (DECL_CONTEXT (node)), |
399 | verbosity); | |
9fb34998 | 400 | put_decl_string (".", 1); |
401 | } | |
402 | if (! DECL_CONSTRUCTOR_P (node)) | |
6bbcd977 | 403 | put_decl_node (DECL_NAME (node), verbosity); |
404 | if (TREE_TYPE (node) != NULL_TREE | |
405 | /* We want to print function parameters only if verbosity | |
406 | is higher than 2. */ | |
407 | && verbosity >= 2) | |
9fb34998 | 408 | { |
409 | int i = 0; | |
410 | tree args = TYPE_ARG_TYPES (TREE_TYPE (node)); | |
411 | if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE) | |
412 | args = TREE_CHAIN (args); | |
413 | put_decl_string ("(", 1); | |
414 | for ( ; args != end_params_node; args = TREE_CHAIN (args), i++) | |
415 | { | |
416 | if (i > 0) | |
417 | put_decl_string (",", 1); | |
6bbcd977 | 418 | put_decl_node (TREE_VALUE (args), verbosity); |
9fb34998 | 419 | } |
420 | put_decl_string (")", 1); | |
377029eb | 421 | } |
377029eb | 422 | } |
9fb34998 | 423 | else |
6bbcd977 | 424 | put_decl_node (DECL_NAME (node), verbosity); |
377029eb | 425 | } |
ce45a448 | 426 | else if (TYPE_P (node) && TYPE_NAME (node) != NULL_TREE) |
377029eb | 427 | { |
6bbcd977 | 428 | if (TREE_CODE (node) == RECORD_TYPE && TYPE_ARRAY_P (node) |
429 | /* Print detailed array information only if verbosity is higher | |
430 | than 2. */ | |
431 | && verbosity >= 2) | |
377029eb | 432 | { |
6bbcd977 | 433 | put_decl_node (TYPE_ARRAY_ELEMENT (node), verbosity); |
377029eb | 434 | put_decl_string("[]", 2); |
435 | } | |
436 | else if (node == promoted_byte_type_node) | |
437 | put_decl_string ("byte", 4); | |
438 | else if (node == promoted_short_type_node) | |
439 | put_decl_string ("short", 5); | |
440 | else if (node == promoted_char_type_node) | |
441 | put_decl_string ("char", 4); | |
442 | else if (node == promoted_boolean_type_node) | |
443 | put_decl_string ("boolean", 7); | |
444 | else if (node == void_type_node && was_pointer) | |
445 | put_decl_string ("null", 4); | |
446 | else | |
6bbcd977 | 447 | put_decl_node (TYPE_NAME (node), verbosity); |
377029eb | 448 | } |
449 | else if (TREE_CODE (node) == IDENTIFIER_NODE) | |
450 | put_decl_string (IDENTIFIER_POINTER (node), IDENTIFIER_LENGTH (node)); | |
451 | else | |
452 | put_decl_string ("<unknown>", -1); | |
453 | } | |
454 | ||
455 | /* Return a user-friendly name for DECL. | |
456 | The resulting string is only valid until the next call. | |
457 | The value of the hook decl_printable_name is this function, | |
6c7ff025 | 458 | which is also called directly by java_print_error_function. */ |
377029eb | 459 | |
2cae41f6 | 460 | const char * |
f33c05c3 | 461 | lang_printable_name (tree decl, int v) |
377029eb | 462 | { |
463 | decl_bufpos = 0; | |
6bbcd977 | 464 | put_decl_node (decl, v); |
b6250dbc | 465 | put_decl_string ("", 1); |
b6250dbc | 466 | return decl_buf; |
467 | } | |
468 | ||
377029eb | 469 | /* Print on stderr the current class and method context. This function |
6c7ff025 | 470 | is the value of the hook print_error_function. */ |
377029eb | 471 | |
1f3233d1 | 472 | static GTY(()) tree last_error_function_context; |
473 | static GTY(()) tree last_error_function; | |
06fa675c | 474 | static void |
2883a3ed | 475 | java_print_error_function (diagnostic_context *context ATTRIBUTE_UNUSED, |
b8c23db3 | 476 | const char *file, |
477 | diagnostic_info *diagnostic ATTRIBUTE_UNUSED) | |
377029eb | 478 | { |
6c7ff025 | 479 | /* Don't print error messages with bogus function prototypes. */ |
480 | if (inhibit_error_function_printing) | |
481 | return; | |
482 | ||
377029eb | 483 | if (current_function_decl != NULL |
484 | && DECL_CONTEXT (current_function_decl) != last_error_function_context) | |
485 | { | |
486 | if (file) | |
487 | fprintf (stderr, "%s: ", file); | |
488 | ||
489 | last_error_function_context = DECL_CONTEXT (current_function_decl); | |
e9ff100d | 490 | fprintf (stderr, "In class '%s':\n", |
5a453052 | 491 | lang_printable_name (last_error_function_context, 0)); |
377029eb | 492 | } |
493 | if (last_error_function != current_function_decl) | |
494 | { | |
495 | if (file) | |
496 | fprintf (stderr, "%s: ", file); | |
497 | ||
498 | if (current_function_decl == NULL) | |
499 | fprintf (stderr, "At top level:\n"); | |
500 | else | |
501 | { | |
68ddcc2a | 502 | const char *name = lang_printable_name (current_function_decl, 2); |
e9ff100d | 503 | fprintf (stderr, "In %s '%s':\n", |
b27ac6b5 | 504 | (DECL_CONSTRUCTOR_P (current_function_decl) ? "constructor" |
9fb34998 | 505 | : "method"), |
506 | name); | |
377029eb | 507 | } |
508 | ||
509 | last_error_function = current_function_decl; | |
510 | } | |
511 | ||
512 | } | |
513 | ||
377029eb | 514 | /* Called to install the PRINT_ERROR_FUNCTION hook differently |
515 | according to LEVEL. LEVEL is 1 during early parsing, when function | |
6c7ff025 | 516 | prototypes aren't fully resolved. java_print_error_function is set |
517 | so it doesn't print incomplete function prototypes. When LEVEL is | |
518 | 2, function prototypes are fully resolved and can be printed when | |
377029eb | 519 | reporting errors. */ |
520 | ||
83a070d0 | 521 | void |
522 | lang_init_source (int level) | |
377029eb | 523 | { |
6c7ff025 | 524 | inhibit_error_function_printing = (level == 1); |
377029eb | 525 | } |
526 | ||
4838a8b6 | 527 | static unsigned int |
528 | java_init_options (unsigned int argc ATTRIBUTE_UNUSED, | |
529 | const char **argv ATTRIBUTE_UNUSED) | |
377029eb | 530 | { |
96f23ba3 | 531 | flag_bounds_check = 1; |
69a1723d | 532 | flag_exceptions = 1; |
533 | flag_non_call_exceptions = 1; | |
350b17ef | 534 | |
535 | /* In Java floating point operations never trap. */ | |
536 | flag_trapping_math = 0; | |
b24bee03 | 537 | |
538 | /* In Java arithmetic overflow always wraps around. */ | |
539 | flag_wrapv = 1; | |
5457b645 | 540 | |
3541e113 | 541 | /* Java requires left-to-right evaluation of subexpressions. */ |
542 | flag_evaluation_order = 1; | |
543 | ||
35171f45 | 544 | jcf_path_init (); |
545 | ||
edc4d549 | 546 | return CL_Java; |
377029eb | 547 | } |
1f3233d1 | 548 | |
08cb25b3 | 549 | /* Post-switch processing. */ |
77e1a5df | 550 | static bool |
03bde601 | 551 | java_post_options (const char **pfilename) |
08cb25b3 | 552 | { |
03bde601 | 553 | const char *filename = *pfilename; |
554 | ||
c6418a4e | 555 | /* Excess precision other than "fast" requires front-end |
556 | support. */ | |
557 | if (flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD | |
558 | && TARGET_FLT_EVAL_METHOD_NON_DEFAULT) | |
559 | sorry ("-fexcess-precision=standard for Java"); | |
560 | flag_excess_precision_cmdline = EXCESS_PRECISION_FAST; | |
561 | ||
a4ccc41f | 562 | /* An absolute requirement: if we're not using indirect dispatch, we |
563 | must always verify everything. */ | |
564 | if (! flag_indirect_dispatch) | |
565 | flag_verify_invocations = true; | |
566 | ||
2e74b8e2 | 567 | if (flag_reduced_reflection) |
568 | { | |
569 | if (flag_indirect_dispatch) | |
570 | error ("-findirect-dispatch is incompatible " | |
571 | "with -freduced-reflection"); | |
572 | if (flag_jni) | |
573 | error ("-fjni is incompatible with -freduced-reflection"); | |
574 | } | |
575 | ||
03bde601 | 576 | /* Open input file. */ |
577 | ||
578 | if (filename == 0 || !strcmp (filename, "-")) | |
579 | { | |
580 | finput = stdin; | |
581 | filename = "stdin"; | |
582 | ||
583 | if (dependency_tracking) | |
584 | error ("can't do dependency tracking with input from stdin"); | |
585 | } | |
586 | else | |
587 | { | |
588 | if (dependency_tracking) | |
589 | { | |
70a000ef | 590 | const char *dot; |
03bde601 | 591 | |
592 | /* If the target is set and the output filename is set, then | |
593 | there's no processing to do here. Otherwise we must | |
594 | compute one or the other. */ | |
595 | if (! ((dependency_tracking & DEPEND_TARGET_SET) | |
596 | && (dependency_tracking & DEPEND_FILE_ALREADY_SET))) | |
597 | { | |
598 | dot = strrchr (filename, '.'); | |
599 | if (dot == NULL) | |
600 | error ("couldn't determine target name for dependency tracking"); | |
601 | else | |
602 | { | |
4c36ffe6 | 603 | char *buf = XNEWVEC (char, dot - filename + |
03bde601 | 604 | 3 + sizeof (TARGET_OBJECT_SUFFIX)); |
605 | strncpy (buf, filename, dot - filename); | |
606 | ||
607 | /* If emitting class files, we might have multiple | |
608 | targets. The class generation code takes care of | |
609 | registering them. Otherwise we compute the | |
610 | target name here. */ | |
611 | if ((dependency_tracking & DEPEND_TARGET_SET)) | |
612 | ; /* Nothing. */ | |
03bde601 | 613 | else |
614 | { | |
615 | strcpy (buf + (dot - filename), TARGET_OBJECT_SUFFIX); | |
616 | jcf_dependency_set_target (buf); | |
617 | } | |
618 | ||
619 | if ((dependency_tracking & DEPEND_FILE_ALREADY_SET)) | |
620 | ; /* Nothing. */ | |
621 | else if ((dependency_tracking & DEPEND_SET_FILE)) | |
622 | { | |
623 | strcpy (buf + (dot - filename), ".d"); | |
624 | jcf_dependency_set_dep_file (buf); | |
625 | } | |
626 | else | |
627 | jcf_dependency_set_dep_file ("-"); | |
628 | ||
629 | free (buf); | |
630 | } | |
631 | } | |
632 | } | |
633 | } | |
931b0a0f | 634 | linemap_add (line_table, LC_ENTER, false, filename, 0); |
635 | linemap_add (line_table, LC_RENAME, false, "<built-in>", 0); | |
03bde601 | 636 | |
77e1a5df | 637 | /* Initialize the compiler back end. */ |
638 | return false; | |
08cb25b3 | 639 | } |
640 | ||
53d20e65 | 641 | /* Return either DECL or its known constant value (if it has one). */ |
642 | ||
643 | tree | |
2883a3ed | 644 | decl_constant_value (tree decl) |
53d20e65 | 645 | { |
646 | if (/* Don't change a variable array bound or initial value to a constant | |
647 | in a place where a variable is invalid. */ | |
648 | current_function_decl != 0 | |
649 | && ! TREE_THIS_VOLATILE (decl) | |
650 | && TREE_READONLY (decl) | |
651 | && DECL_INITIAL (decl) != 0 | |
652 | && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK | |
653 | /* This is invalid if initial value is not constant. | |
654 | If it has either a function call, a memory reference, | |
655 | or a variable, then re-evaluating it could give different results. */ | |
656 | && TREE_CONSTANT (DECL_INITIAL (decl)) | |
657 | /* Check for cases where this is sub-optimal, even though valid. */ | |
658 | && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR) | |
659 | return DECL_INITIAL (decl); | |
660 | return decl; | |
661 | } | |
662 | ||
16ceebae | 663 | /* Every call to a static constructor has an associated boolean |
664 | variable which is in the outermost scope of the calling method. | |
665 | This variable is used to avoid multiple calls to the static | |
b27ac6b5 | 666 | constructor for each class. |
16ceebae | 667 | |
4f9026a9 | 668 | It looks something like this: |
16ceebae | 669 | |
670 | foo () | |
671 | { | |
672 | boolean dummy = OtherClass.is_initialized; | |
b27ac6b5 | 673 | |
16ceebae | 674 | ... |
b27ac6b5 | 675 | |
16ceebae | 676 | if (! dummy) |
677 | OtherClass.initialize(); | |
678 | ||
679 | ... use OtherClass.data ... | |
680 | } | |
681 | ||
682 | Each of these boolean variables has an entry in the | |
683 | DECL_FUNCTION_INIT_TEST_TABLE of a method. When inlining a method | |
684 | we must merge the DECL_FUNCTION_INIT_TEST_TABLE from the function | |
4f9026a9 | 685 | being inlined and create the boolean variables in the outermost |
16ceebae | 686 | scope of the method being inlined into. */ |
687 | ||
688 | /* Create a mapping from a boolean variable in a method being inlined | |
689 | to one in the scope of the method being inlined into. */ | |
690 | ||
691 | static int | |
2883a3ed | 692 | merge_init_test_initialization (void **entry, void *x) |
16ceebae | 693 | { |
694 | struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry; | |
695 | splay_tree decl_map = (splay_tree)x; | |
696 | splay_tree_node n; | |
697 | tree *init_test_decl; | |
b27ac6b5 | 698 | |
16ceebae | 699 | /* See if we have remapped this declaration. If we haven't there's |
700 | a bug in the inliner. */ | |
701 | n = splay_tree_lookup (decl_map, (splay_tree_key) ite->value); | |
bc031ffe | 702 | gcc_assert (n); |
16ceebae | 703 | |
704 | /* Create a new entry for the class and its remapped boolean | |
705 | variable. If we already have a mapping for this class we've | |
706 | already initialized it, so don't overwrite the value. */ | |
707 | init_test_decl = java_treetreehash_new | |
708 | (DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), ite->key); | |
709 | if (!*init_test_decl) | |
710 | *init_test_decl = (tree)n->value; | |
711 | ||
b27ac6b5 | 712 | /* This fixes a weird case. |
a34d7aaf | 713 | |
714 | The front end assumes that once we have called a method that | |
715 | initializes some class, we can assume the class is initialized. It | |
716 | does this by setting the DECL_INITIAL of the init_test_decl for that | |
717 | class, and no initializations are emitted for that class. | |
b27ac6b5 | 718 | |
34882fef | 719 | However, what if the method that is supposed to do the initialization |
a34d7aaf | 720 | is itself inlined in the caller? When expanding the called method |
11da80f9 | 721 | we'll assume that the class initialization has already been done, |
a34d7aaf | 722 | because the DECL_INITIAL of the init_test_decl is set. |
b27ac6b5 | 723 | |
a34d7aaf | 724 | To fix this we remove the DECL_INITIAL (in the caller scope) of all |
725 | the init_test_decls corresponding to classes initialized by the | |
726 | inlined method. This makes the caller no longer assume that the | |
727 | method being inlined does any class initializations. */ | |
728 | DECL_INITIAL (*init_test_decl) = NULL; | |
729 | ||
16ceebae | 730 | return true; |
731 | } | |
732 | ||
733 | /* Merge the DECL_FUNCTION_INIT_TEST_TABLE from the function we're | |
734 | inlining. */ | |
735 | ||
736 | void | |
2883a3ed | 737 | java_inlining_merge_static_initializers (tree fn, void *decl_map) |
16ceebae | 738 | { |
b27ac6b5 | 739 | htab_traverse |
16ceebae | 740 | (DECL_FUNCTION_INIT_TEST_TABLE (fn), |
741 | merge_init_test_initialization, decl_map); | |
742 | } | |
743 | ||
744 | /* Lookup a DECL_FUNCTION_INIT_TEST_TABLE entry in the method we're | |
745 | inlining into. If we already have a corresponding entry in that | |
746 | class we don't need to create another one, so we create a mapping | |
747 | from the variable in the inlined class to the corresponding | |
748 | pre-existing one. */ | |
749 | ||
750 | static int | |
2883a3ed | 751 | inline_init_test_initialization (void **entry, void *x) |
16ceebae | 752 | { |
753 | struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry; | |
754 | splay_tree decl_map = (splay_tree)x; | |
b27ac6b5 | 755 | |
756 | tree h = java_treetreehash_find | |
16ceebae | 757 | (DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), ite->key); |
758 | if (! h) | |
759 | return true; | |
16ceebae | 760 | splay_tree_insert (decl_map, |
761 | (splay_tree_key) ite->value, | |
762 | (splay_tree_value) h); | |
16ceebae | 763 | return true; |
764 | } | |
765 | ||
766 | /* Look up the boolean variables in the DECL_FUNCTION_INIT_TEST_TABLE | |
767 | of a method being inlined. For each hone, if we already have a | |
768 | variable associated with the same class in the method being inlined | |
769 | into, create a new mapping for it. */ | |
770 | ||
771 | void | |
2883a3ed | 772 | java_inlining_map_static_initializers (tree fn, void *decl_map) |
16ceebae | 773 | { |
b27ac6b5 | 774 | htab_traverse |
16ceebae | 775 | (DECL_FUNCTION_INIT_TEST_TABLE (fn), |
776 | inline_init_test_initialization, decl_map); | |
777 | } | |
778 | ||
03e05510 | 779 | /* Avoid voluminous output for deep recursion of compound exprs. */ |
780 | ||
781 | static void | |
2883a3ed | 782 | dump_compound_expr (dump_info_p di, tree t) |
03e05510 | 783 | { |
784 | int i; | |
785 | ||
786 | for (i=0; i<2; i++) | |
787 | { | |
788 | switch (TREE_CODE (TREE_OPERAND (t, i))) | |
789 | { | |
790 | case COMPOUND_EXPR: | |
791 | dump_compound_expr (di, TREE_OPERAND (t, i)); | |
792 | break; | |
793 | ||
03e05510 | 794 | default: |
795 | dump_child ("expr", TREE_OPERAND (t, i)); | |
796 | } | |
797 | } | |
798 | } | |
b27ac6b5 | 799 | |
fb84380a | 800 | static bool |
2883a3ed | 801 | java_dump_tree (void *dump_info, tree t) |
03e05510 | 802 | { |
803 | enum tree_code code; | |
804 | dump_info_p di = (dump_info_p) dump_info; | |
805 | ||
806 | /* Figure out what kind of node this is. */ | |
807 | code = TREE_CODE (t); | |
808 | ||
809 | switch (code) | |
810 | { | |
811 | case FUNCTION_DECL: | |
812 | dump_child ("args", DECL_ARGUMENTS (t)); | |
813 | if (DECL_EXTERNAL (t)) | |
814 | dump_string (di, "undefined"); | |
815 | if (TREE_PUBLIC (t)) | |
816 | dump_string (di, "extern"); | |
817 | else | |
818 | dump_string (di, "static"); | |
03e05510 | 819 | if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t)) |
820 | dump_child ("inline body", DECL_SAVED_TREE (t)); | |
fb84380a | 821 | return true; |
03e05510 | 822 | |
823 | case RETURN_EXPR: | |
824 | dump_child ("expr", TREE_OPERAND (t, 0)); | |
fb84380a | 825 | return true; |
03e05510 | 826 | |
827 | case GOTO_EXPR: | |
828 | dump_child ("goto", TREE_OPERAND (t, 0)); | |
fb84380a | 829 | return true; |
03e05510 | 830 | |
831 | case LABEL_EXPR: | |
832 | dump_child ("label", TREE_OPERAND (t, 0)); | |
fb84380a | 833 | return true; |
03e05510 | 834 | |
03e05510 | 835 | case BLOCK: |
836 | if (BLOCK_EXPR_BODY (t)) | |
837 | { | |
838 | tree local = BLOCK_VARS (t); | |
839 | while (local) | |
840 | { | |
841 | tree next = TREE_CHAIN (local); | |
842 | dump_child ("var", local); | |
843 | local = next; | |
844 | } | |
b27ac6b5 | 845 | |
03e05510 | 846 | { |
847 | tree block = BLOCK_EXPR_BODY (t); | |
848 | dump_child ("body", block); | |
849 | block = TREE_CHAIN (block); | |
850 | } | |
851 | } | |
fb84380a | 852 | return true; |
b27ac6b5 | 853 | |
03e05510 | 854 | case COMPOUND_EXPR: |
855 | if (!dump_flag (di, TDF_SLIM, t)) | |
fb84380a | 856 | return false; |
03e05510 | 857 | dump_compound_expr (di, t); |
fb84380a | 858 | return true; |
03e05510 | 859 | |
860 | default: | |
861 | break; | |
862 | } | |
fb84380a | 863 | return false; |
03e05510 | 864 | } |
e2e9c55b | 865 | |
866 | /* Java calls can't, in general, be sibcalls because we need an | |
867 | accurate stack trace in order to guarantee correct operation of | |
868 | methods such as Class.forName(String) and | |
869 | SecurityManager.getClassContext(). */ | |
870 | ||
871 | static bool | |
9f627b1a | 872 | java_decl_ok_for_sibcall (const_tree decl) |
e2e9c55b | 873 | { |
65bf3316 | 874 | return (decl != NULL && DECL_CONTEXT (decl) == output_class |
73b5e722 | 875 | && !DECL_UNINLINABLE (decl)); |
e2e9c55b | 876 | } |
877 | ||
03a61d93 | 878 | static enum classify_record |
879 | java_classify_record (tree type) | |
880 | { | |
881 | if (! CLASS_P (type)) | |
882 | return RECORD_IS_STRUCT; | |
883 | ||
2b888771 | 884 | if (CLASS_INTERFACE (TYPE_NAME (type))) |
03a61d93 | 885 | return RECORD_IS_INTERFACE; |
886 | ||
887 | return RECORD_IS_CLASS; | |
888 | } | |
889 | ||
58d82cd0 | 890 | static GTY(()) tree java_eh_personality_decl; |
891 | ||
892 | static tree | |
893 | java_eh_personality (void) | |
894 | { | |
895 | if (!java_eh_personality_decl) | |
896 | java_eh_personality_decl | |
897 | = build_personality_function (USING_SJLJ_EXCEPTIONS | |
898 | ? "__gcj_personality_sj0" | |
899 | : "__gcj_personality_v0"); | |
900 | ||
901 | return java_eh_personality_decl; | |
902 | } | |
903 | ||
1f3233d1 | 904 | #include "gt-java-lang.h" |