1 /* Handle exceptions for GNU compiler for the Java(TM) language.
2 Copyright (C) 1997-2015 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GCC is distributed in the hope that it will be useful,
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.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>.
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. */
26 #include "coretypes.h"
31 #include "double-int.h"
38 #include "fold-const.h"
39 #include "stringpool.h"
40 #include "stor-layout.h"
41 #include "java-tree.h"
43 #include "java-opcodes.h"
45 #include "java-except.h"
46 #include "diagnostic-core.h"
48 #include "tree-iterator.h"
51 static void expand_start_java_handler (struct eh_range
*);
52 static struct eh_range
*find_handler_in_range (int, struct eh_range
*,
54 static void check_start_handlers (struct eh_range
*, int);
55 static void free_eh_ranges (struct eh_range
*range
);
57 struct eh_range
*current_method_handlers
;
59 struct eh_range
*current_try_block
= NULL
;
61 /* These variables are used to speed up find_handler. */
63 static int cache_range_start
, cache_range_end
;
64 static struct eh_range
*cache_range
;
65 static struct eh_range
*cache_next_child
;
67 /* A dummy range that represents the entire method. */
69 struct eh_range whole_range
;
71 /* Check the invariants of the structure we're using to contain
72 exception regions. Either returns true or fails an assertion
76 sanity_check_exception_range (struct eh_range
*range
)
78 struct eh_range
*ptr
= range
->first_child
;
79 for (; ptr
; ptr
= ptr
->next_sibling
)
81 gcc_assert (ptr
->outer
== range
82 && ptr
->end_pc
> ptr
->start_pc
);
83 if (ptr
->next_sibling
)
84 gcc_assert (ptr
->next_sibling
->start_pc
>= ptr
->end_pc
);
85 gcc_assert (ptr
->start_pc
>= ptr
->outer
->start_pc
86 && ptr
->end_pc
<= ptr
->outer
->end_pc
);
87 (void) sanity_check_exception_range (ptr
);
92 #if defined(DEBUG_JAVA_BINDING_LEVELS)
93 extern int is_class_level
;
94 extern int current_pc
;
95 extern int binding_depth
;
96 extern void indent (void);
98 print_ranges (struct eh_range
*range
)
103 struct eh_range
*child
= range
->first_child
;
106 fprintf (stderr
, "handler pc %d --> %d ", range
->start_pc
, range
->end_pc
);
108 tree handler
= range
->handlers
;
109 for ( ; handler
!= NULL_TREE
; handler
= TREE_CHAIN (handler
))
111 tree type
= TREE_PURPOSE (handler
);
113 type
= throwable_type_node
;
114 fprintf (stderr
, " type=%s ", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type
))));
116 fprintf (stderr
, "\n");
118 int saved
= binding_depth
;
120 print_ranges (child
);
121 binding_depth
= saved
;
123 print_ranges (range
->next_sibling
);
127 /* Search for the most specific eh_range containing PC.
128 Assume PC is within RANGE.
129 CHILD is a list of children of RANGE such that any
130 previous children have end_pc values that are too low. */
132 static struct eh_range
*
133 find_handler_in_range (int pc
, struct eh_range
*range
, struct eh_range
*child
)
135 for (; child
!= NULL
; child
= child
->next_sibling
)
137 if (pc
< child
->start_pc
)
139 if (pc
< child
->end_pc
)
140 return find_handler_in_range (pc
, child
, child
->first_child
);
143 cache_range_start
= pc
;
144 cache_next_child
= child
;
145 cache_range_end
= child
== NULL
? range
->end_pc
: child
->start_pc
;
149 /* Find the inner-most handler that contains PC. */
152 find_handler (int pc
)
155 if (pc
>= cache_range_start
)
158 if (pc
< cache_range_end
)
160 while (pc
>= h
->end_pc
)
162 cache_next_child
= h
->next_sibling
;
169 cache_next_child
= h
->first_child
;
171 return find_handler_in_range (pc
, h
, cache_next_child
);
175 free_eh_ranges (struct eh_range
*range
)
179 struct eh_range
*next
= range
->next_sibling
;
180 free_eh_ranges (range
->first_child
);
181 if (range
!= &whole_range
)
187 /* Called to re-initialize the exception machinery for a new method. */
190 method_init_exceptions (void)
192 free_eh_ranges (&whole_range
);
193 whole_range
.start_pc
= 0;
194 whole_range
.end_pc
= DECL_CODE_LENGTH (current_function_decl
) + 1;
195 whole_range
.outer
= NULL
;
196 whole_range
.first_child
= NULL
;
197 whole_range
.next_sibling
= NULL
;
198 cache_range_start
= 0xFFFFFF;
201 /* Split an exception range into two at PC. The sub-ranges that
202 belong to the range are split and distributed between the two new
206 split_range (struct eh_range
*range
, int pc
)
208 struct eh_range
*ptr
;
209 struct eh_range
**first_child
, **second_child
;
212 /* First, split all the sub-ranges. */
213 for (ptr
= range
->first_child
; ptr
; ptr
= ptr
->next_sibling
)
215 if (pc
> ptr
->start_pc
218 split_range (ptr
, pc
);
222 /* Create a new range. */
223 h
= XNEW (struct eh_range
);
226 h
->end_pc
= range
->end_pc
;
227 h
->next_sibling
= range
->next_sibling
;
228 range
->next_sibling
= h
;
230 h
->handlers
= build_tree_list (TREE_PURPOSE (range
->handlers
),
231 TREE_VALUE (range
->handlers
));
232 h
->next_sibling
= NULL
;
235 h
->outer
= range
->outer
;
236 h
->first_child
= NULL
;
238 ptr
= range
->first_child
;
239 first_child
= &range
->first_child
;
240 second_child
= &h
->first_child
;
242 /* Distribute the sub-ranges between the two new ranges. */
243 for (ptr
= range
->first_child
; ptr
; ptr
= ptr
->next_sibling
)
245 if (ptr
->start_pc
< pc
)
249 first_child
= &ptr
->next_sibling
;
255 second_child
= &ptr
->next_sibling
;
259 *second_child
= NULL
;
263 /* Add an exception range.
265 There are some missed optimization opportunities here. For
266 example, some bytecode obfuscators generate seemingly
267 nonoverlapping exception ranges which, when coalesced, do in fact
268 nest correctly. We could merge these, but we'd have to fix up all
269 the enclosed regions first and perhaps create a new range anyway if
270 it overlapped existing ranges.
272 Also, we don't attempt to detect the case where two previously
273 added disjoint ranges could be coalesced by a new range. */
276 add_handler (int start_pc
, int end_pc
, tree handler
, tree type
)
278 struct eh_range
*ptr
, *h
;
279 struct eh_range
**first_child
, **prev
;
281 /* First, split all the existing ranges that we need to enclose. */
282 for (ptr
= whole_range
.first_child
; ptr
; ptr
= ptr
->next_sibling
)
284 if (start_pc
> ptr
->start_pc
285 && start_pc
< ptr
->end_pc
)
287 split_range (ptr
, start_pc
);
290 if (end_pc
> ptr
->start_pc
291 && end_pc
< ptr
->end_pc
)
293 split_range (ptr
, end_pc
);
296 if (ptr
->start_pc
>= end_pc
)
300 /* Create the new range. */
301 h
= XNEW (struct eh_range
);
302 first_child
= &h
->first_child
;
304 h
->start_pc
= start_pc
;
306 h
->first_child
= NULL
;
307 h
->outer
= NULL_EH_RANGE
;
308 h
->handlers
= build_tree_list (type
, handler
);
309 h
->next_sibling
= NULL
;
313 /* Find every range at the top level that will be a sub-range of the
314 range we're inserting and make it so. */
316 struct eh_range
**prev
= &whole_range
.first_child
;
317 for (ptr
= *prev
; ptr
;)
319 struct eh_range
*next
= ptr
->next_sibling
;
321 if (ptr
->start_pc
>= end_pc
)
324 if (ptr
->start_pc
< start_pc
)
326 prev
= &ptr
->next_sibling
;
328 else if (ptr
->start_pc
>= start_pc
329 && ptr
->start_pc
< end_pc
)
333 first_child
= &ptr
->next_sibling
;
335 ptr
->next_sibling
= NULL
;
342 /* Find the right place to insert the new range. */
343 prev
= &whole_range
.first_child
;
344 for (ptr
= *prev
; ptr
; prev
= &ptr
->next_sibling
, ptr
= ptr
->next_sibling
)
346 gcc_assert (ptr
->outer
== NULL_EH_RANGE
);
347 if (ptr
->start_pc
>= start_pc
)
351 /* And insert it there. */
355 h
->next_sibling
= ptr
;
356 h
->outer
= ptr
->outer
;
361 /* if there are any handlers for this range, issue start of region */
363 expand_start_java_handler (struct eh_range
*range
)
365 #if defined(DEBUG_JAVA_BINDING_LEVELS)
367 fprintf (stderr
, "expand start handler pc %d --> %d\n",
368 current_pc
, range
->end_pc
);
369 #endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
371 register_exception_range (range
, range
->start_pc
, range
->end_pc
);
376 prepare_eh_table_type (tree type
)
385 /* The "type" (match_info) in a (Java) exception table is a pointer to:
386 * a) NULL - meaning match any type in a try-finally.
387 * b) a pointer to a pointer to a class.
388 * c) a pointer to a pointer to a utf8_ref. The pointer is
389 * rewritten to point to the appropriate class. */
391 if (type
== NULL_TREE
)
394 if (TYPE_TO_RUNTIME_MAP (output_class
) == NULL
)
395 TYPE_TO_RUNTIME_MAP (output_class
) = java_treetreehash_create (10);
397 slot
= java_treetreehash_new (TYPE_TO_RUNTIME_MAP (output_class
), type
);
399 return TREE_VALUE (*slot
);
401 if (is_compiled_class (type
) && !flag_indirect_dispatch
)
403 name
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type
)));
404 buf
= (char *) alloca (strlen (name
) + 5);
405 sprintf (buf
, "%s_ref", name
);
406 decl
= build_decl (input_location
,
407 VAR_DECL
, get_identifier (buf
), ptr_type_node
);
408 TREE_STATIC (decl
) = 1;
409 DECL_ARTIFICIAL (decl
) = 1;
410 DECL_IGNORED_P (decl
) = 1;
411 TREE_READONLY (decl
) = 1;
412 TREE_THIS_VOLATILE (decl
) = 0;
413 DECL_INITIAL (decl
) = build_class_ref (type
);
414 layout_decl (decl
, 0);
416 exp
= build1 (ADDR_EXPR
, build_pointer_type (TREE_TYPE (decl
)), decl
);
420 utf8_ref
= build_utf8_ref (DECL_NAME (TYPE_NAME (type
)));
421 name
= IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (utf8_ref
, 0)));
422 buf
= (char *) alloca (strlen (name
) + 5);
423 sprintf (buf
, "%s_ref", name
);
424 decl
= build_decl (input_location
,
425 VAR_DECL
, get_identifier (buf
), utf8const_ptr_type
);
426 TREE_STATIC (decl
) = 1;
427 DECL_ARTIFICIAL (decl
) = 1;
428 DECL_IGNORED_P (decl
) = 1;
429 TREE_READONLY (decl
) = 1;
430 TREE_THIS_VOLATILE (decl
) = 0;
431 layout_decl (decl
, 0);
433 exp
= build1 (ADDR_EXPR
, build_pointer_type (utf8const_ptr_type
), decl
);
434 CONSTRUCTOR_APPEND_ELT (TYPE_CATCH_CLASSES (output_class
),
436 make_catch_class_record (exp
, utf8_ref
));
439 exp
= convert (ptr_type_node
, exp
);
441 *slot
= tree_cons (type
, exp
, NULL_TREE
);
447 expand_catch_class (treetreehash_entry
**entry
, int)
449 struct treetreehash_entry
*ite
= *entry
;
450 tree addr
= TREE_VALUE ((tree
)ite
->value
);
453 decl
= TREE_OPERAND (addr
, 0);
454 rest_of_decl_compilation (decl
, global_bindings_p (), 0);
458 /* For every class in the TYPE_TO_RUNTIME_MAP, expand the
459 corresponding object that is used by the runtime type matcher. */
462 java_expand_catch_classes (tree this_class
)
464 if (TYPE_TO_RUNTIME_MAP (this_class
))
465 TYPE_TO_RUNTIME_MAP (this_class
)->traverse
<int, expand_catch_class
> (0);
468 /* Build and push the variable that will hold the exception object
469 within this function. */
472 build_exception_object_var (void)
474 tree decl
= DECL_FUNCTION_EXC_OBJ (current_function_decl
);
477 decl
= build_decl (DECL_SOURCE_LOCATION (current_function_decl
),
478 VAR_DECL
, get_identifier ("#exc_obj"), ptr_type_node
);
479 DECL_IGNORED_P (decl
) = 1;
480 DECL_ARTIFICIAL (decl
) = 1;
482 DECL_FUNCTION_EXC_OBJ (current_function_decl
) = decl
;
483 pushdecl_function_level (decl
);
488 /* Build a reference to the jthrowable object being carried in the
492 build_exception_object_ref (tree type
)
496 /* Java only passes object via pointer and doesn't require adjusting.
497 The java object is immediately before the generic exception header. */
498 obj
= build_exception_object_var ();
499 obj
= fold_convert (build_pointer_type (type
), obj
);
500 obj
= fold_build_pointer_plus (obj
,
501 fold_build1 (NEGATE_EXPR
, sizetype
,
502 TYPE_SIZE_UNIT (TREE_TYPE (obj
))));
503 obj
= build1 (INDIRECT_REF
, type
, obj
);
508 /* If there are any handlers for this range, issue end of range,
509 and then all handler blocks */
511 expand_end_java_handler (struct eh_range
*range
)
513 tree handler
= range
->handlers
;
516 tree exc_obj
= build_exception_object_var ();
517 tree catches
= make_node (STATEMENT_LIST
);
518 tree_stmt_iterator catches_i
= tsi_last (catches
);
521 for (; handler
; handler
= TREE_CHAIN (handler
))
523 tree type
, eh_type
, x
;
524 tree stmts
= make_node (STATEMENT_LIST
);
525 tree_stmt_iterator stmts_i
= tsi_last (stmts
);
527 type
= TREE_PURPOSE (handler
);
529 type
= throwable_type_node
;
530 eh_type
= prepare_eh_table_type (type
);
532 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_EH_POINTER
),
533 1, integer_zero_node
);
534 x
= build2 (MODIFY_EXPR
, void_type_node
, exc_obj
, x
);
535 tsi_link_after (&stmts_i
, x
, TSI_CONTINUE_LINKING
);
537 x
= build1 (GOTO_EXPR
, void_type_node
, TREE_VALUE (handler
));
538 tsi_link_after (&stmts_i
, x
, TSI_CONTINUE_LINKING
);
540 x
= build2 (CATCH_EXPR
, void_type_node
, eh_type
, stmts
);
541 tsi_link_after (&catches_i
, x
, TSI_CONTINUE_LINKING
);
543 /* Throwable can match anything in Java, and therefore
544 any subsequent handlers are unreachable. */
545 /* ??? If we're assured of no foreign language exceptions,
546 we'd be better off using NULL as the exception type
548 if (type
== throwable_type_node
)
553 *body
= build2 (TRY_CATCH_EXPR
, void_type_node
, *body
, catches
);
556 #if defined(DEBUG_JAVA_BINDING_LEVELS)
558 fprintf (stderr
, "expand end handler pc %d <-- %d\n",
559 current_pc
, range
->start_pc
);
560 #endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
563 /* Recursive helper routine for maybe_start_handlers. */
566 check_start_handlers (struct eh_range
*range
, int pc
)
568 if (range
!= NULL_EH_RANGE
&& range
->start_pc
== pc
)
570 check_start_handlers (range
->outer
, pc
);
571 if (!range
->expanded
)
572 expand_start_java_handler (range
);
577 /* Routine to see if exception handling is turned on.
578 DO_WARN is nonzero if we want to inform the user that exception
579 handling is turned off.
581 This is used to ensure that -fexceptions has been specified if the
582 compiler tries to use any exception-specific functions. */
587 if (! flag_exceptions
)
589 static int warned
= 0;
592 error ("exception handling disabled, use -fexceptions to enable");
600 static struct eh_range
*current_range
;
602 /* Emit any start-of-try-range starting at start_pc and ending after
606 maybe_start_try (int start_pc
, int end_pc
)
608 struct eh_range
*range
;
612 range
= find_handler (start_pc
);
613 while (range
!= NULL_EH_RANGE
&& range
->start_pc
== start_pc
614 && range
->end_pc
< end_pc
)
615 range
= range
->outer
;
617 current_range
= range
;
618 check_start_handlers (range
, start_pc
);