1/* Handle exceptions for GNU compiler for the Java(TM) language. 2 Copyright (C) 1997-2015 Free Software Foundation, Inc. 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 3, or (at your option) 9any later version. 10 11GCC is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with GCC; see the file COPYING3. If not see 18<http://www.gnu.org/licenses/>. 19 20Java and all Java-based marks are trademarks or registered trademarks 21of Sun Microsystems, Inc. in the United States and other countries. 22The Free Software Foundation is independent of Sun Microsystems, Inc. */ 23 24#include "config.h" 25#include "system.h" 26#include "coretypes.h" 27#include "tm.h" 28#include "hash-set.h" 29#include "machmode.h" 30#include "vec.h" 31#include "double-int.h" 32#include "input.h" 33#include "alias.h" 34#include "symtab.h" 35#include "wide-int.h" 36#include "inchash.h" 37#include "tree.h" 38#include "fold-const.h" 39#include "stringpool.h" 40#include "stor-layout.h" 41#include "java-tree.h" 42#include "javaop.h" 43#include "java-opcodes.h" 44#include "jcf.h" 45#include "java-except.h" 46#include "diagnostic-core.h" 47#include "toplev.h" 48#include "tree-iterator.h" 49 50 51static void expand_start_java_handler (struct eh_range *); 52static struct eh_range *find_handler_in_range (int, struct eh_range *, 53 struct eh_range *); 54static void check_start_handlers (struct eh_range *, int); 55static void free_eh_ranges (struct eh_range *range); 56 57struct eh_range *current_method_handlers; 58 59struct eh_range *current_try_block = NULL; 60 61/* These variables are used to speed up find_handler. */ 62 63static int cache_range_start, cache_range_end; 64static struct eh_range *cache_range; 65static struct eh_range *cache_next_child; 66 67/* A dummy range that represents the entire method. */ 68 69struct eh_range whole_range; 70 71/* Check the invariants of the structure we're using to contain 72 exception regions. Either returns true or fails an assertion 73 check. */ 74 75bool 76sanity_check_exception_range (struct eh_range *range) 77{ 78 struct eh_range *ptr = range->first_child; 79 for (; ptr; ptr = ptr->next_sibling) 80 { 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); 88 } 89 return true; 90} 91 92#if defined(DEBUG_JAVA_BINDING_LEVELS) 93extern int is_class_level; 94extern int current_pc; 95extern int binding_depth; 96extern void indent (void); 97static void 98print_ranges (struct eh_range *range) 99{ 100 if (! range) 101 return; 102 103 struct eh_range *child = range->first_child; 104 105 indent (); 106 fprintf (stderr, "handler pc %d --> %d ", range->start_pc, range->end_pc); 107 108 tree handler = range->handlers; 109 for ( ; handler != NULL_TREE; handler = TREE_CHAIN (handler)) 110 { 111 tree type = TREE_PURPOSE (handler); 112 if (type == NULL) 113 type = throwable_type_node; 114 fprintf (stderr, " type=%s ", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); 115 } 116 fprintf (stderr, "\n"); 117 118 int saved = binding_depth; 119 binding_depth++; 120 print_ranges (child); 121 binding_depth = saved; 122 123 print_ranges (range->next_sibling); 124} 125#endif 126 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. */ 131 132static struct eh_range * 133find_handler_in_range (int pc, struct eh_range *range, struct eh_range *child) 134{ 135 for (; child != NULL; child = child->next_sibling) 136 { 137 if (pc < child->start_pc) 138 break; 139 if (pc < child->end_pc) 140 return find_handler_in_range (pc, child, child->first_child); 141 } 142 cache_range = range; 143 cache_range_start = pc; 144 cache_next_child = child; 145 cache_range_end = child == NULL ? range->end_pc : child->start_pc; 146 return range; 147} 148 149/* Find the inner-most handler that contains PC. */ 150 151struct eh_range * 152find_handler (int pc) 153{ 154 struct eh_range *h; 155 if (pc >= cache_range_start) 156 { 157 h = cache_range; 158 if (pc < cache_range_end) 159 return h; 160 while (pc >= h->end_pc) 161 { 162 cache_next_child = h->next_sibling; 163 h = h->outer; 164 } 165 } 166 else 167 { 168 h = &whole_range; 169 cache_next_child = h->first_child; 170 } 171 return find_handler_in_range (pc, h, cache_next_child); 172} 173 174static void 175free_eh_ranges (struct eh_range *range) 176{ 177 while (range) 178 { 179 struct eh_range *next = range->next_sibling; 180 free_eh_ranges (range->first_child); 181 if (range != &whole_range) 182 free (range); 183 range = next; 184 } 185} 186 187/* Called to re-initialize the exception machinery for a new method. */ 188 189void 190method_init_exceptions (void) 191{ 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; 199} 200 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 203 ranges. */ 204 205static void 206split_range (struct eh_range *range, int pc) 207{ 208 struct eh_range *ptr; 209 struct eh_range **first_child, **second_child; 210 struct eh_range *h; 211 212 /* First, split all the sub-ranges. */ 213 for (ptr = range->first_child; ptr; ptr = ptr->next_sibling) 214 { 215 if (pc > ptr->start_pc 216 && pc < ptr->end_pc) 217 { 218 split_range (ptr, pc); 219 } 220 } 221 222 /* Create a new range. */ 223 h = XNEW (struct eh_range); 224 225 h->start_pc = pc; 226 h->end_pc = range->end_pc; 227 h->next_sibling = range->next_sibling; 228 range->next_sibling = h; 229 range->end_pc = pc; 230 h->handlers = build_tree_list (TREE_PURPOSE (range->handlers), 231 TREE_VALUE (range->handlers)); 232 h->next_sibling = NULL; 233 h->expanded = 0; 234 h->stmt = NULL; 235 h->outer = range->outer; 236 h->first_child = NULL; 237 238 ptr = range->first_child; 239 first_child = &range->first_child; 240 second_child = &h->first_child; 241 242 /* Distribute the sub-ranges between the two new ranges. */ 243 for (ptr = range->first_child; ptr; ptr = ptr->next_sibling) 244 { 245 if (ptr->start_pc < pc) 246 { 247 *first_child = ptr; 248 ptr->outer = range; 249 first_child = &ptr->next_sibling; 250 } 251 else 252 { 253 *second_child = ptr; 254 ptr->outer = h; 255 second_child = &ptr->next_sibling; 256 } 257 } 258 *first_child = NULL; 259 *second_child = NULL; 260} 261 262 263/* Add an exception range. 264 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. 271 272 Also, we don't attempt to detect the case where two previously 273 added disjoint ranges could be coalesced by a new range. */ 274 275void 276add_handler (int start_pc, int end_pc, tree handler, tree type) 277{ 278 struct eh_range *ptr, *h; 279 struct eh_range **first_child, **prev; 280 281 /* First, split all the existing ranges that we need to enclose. */ 282 for (ptr = whole_range.first_child; ptr; ptr = ptr->next_sibling) 283 { 284 if (start_pc > ptr->start_pc 285 && start_pc < ptr->end_pc) 286 { 287 split_range (ptr, start_pc); 288 } 289 290 if (end_pc > ptr->start_pc 291 && end_pc < ptr->end_pc) 292 { 293 split_range (ptr, end_pc); 294 } 295 296 if (ptr->start_pc >= end_pc) 297 break; 298 } 299 300 /* Create the new range. */ 301 h = XNEW (struct eh_range); 302 first_child = &h->first_child; 303 304 h->start_pc = start_pc; 305 h->end_pc = end_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; 310 h->expanded = 0; 311 h->stmt = NULL; 312 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. */ 315 { 316 struct eh_range **prev = &whole_range.first_child; 317 for (ptr = *prev; ptr;) 318 { 319 struct eh_range *next = ptr->next_sibling; 320 321 if (ptr->start_pc >= end_pc) 322 break; 323 324 if (ptr->start_pc < start_pc) 325 { 326 prev = &ptr->next_sibling; 327 } 328 else if (ptr->start_pc >= start_pc 329 && ptr->start_pc < end_pc) 330 { 331 *prev = next; 332 *first_child = ptr; 333 first_child = &ptr->next_sibling; 334 ptr->outer = h; 335 ptr->next_sibling = NULL; 336 } 337 338 ptr = next; 339 } 340 } 341 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) 345 { 346 gcc_assert (ptr->outer == NULL_EH_RANGE); 347 if (ptr->start_pc >= start_pc) 348 break; 349 } 350 351 /* And insert it there. */ 352 *prev = h; 353 if (ptr) 354 { 355 h->next_sibling = ptr; 356 h->outer = ptr->outer; 357 } 358} 359 360 361/* if there are any handlers for this range, issue start of region */ 362static void 363expand_start_java_handler (struct eh_range *range) 364{ 365#if defined(DEBUG_JAVA_BINDING_LEVELS) 366 indent (); 367 fprintf (stderr, "expand start handler pc %d --> %d\n", 368 current_pc, range->end_pc); 369#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */ 370 pushlevel (0); 371 register_exception_range (range, range->start_pc, range->end_pc); 372 range->expanded = 1; 373} 374 375tree 376prepare_eh_table_type (tree type) 377{ 378 tree exp; 379 tree *slot; 380 const char *name; 381 char *buf; 382 tree decl; 383 tree utf8_ref; 384 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. */ 390 391 if (type == NULL_TREE) 392 return NULL_TREE; 393 394 if (TYPE_TO_RUNTIME_MAP (output_class) == NULL) 395 TYPE_TO_RUNTIME_MAP (output_class) = java_treetreehash_create (10); 396 397 slot = java_treetreehash_new (TYPE_TO_RUNTIME_MAP (output_class), type); 398 if (*slot != NULL) 399 return TREE_VALUE (*slot); 400 401 if (is_compiled_class (type) && !flag_indirect_dispatch) 402 { 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); 415 pushdecl (decl); 416 exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (decl)), decl); 417 } 418 else 419 { 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); 432 pushdecl (decl); 433 exp = build1 (ADDR_EXPR, build_pointer_type (utf8const_ptr_type), decl); 434 CONSTRUCTOR_APPEND_ELT (TYPE_CATCH_CLASSES (output_class), 435 NULL_TREE, 436 make_catch_class_record (exp, utf8_ref)); 437 } 438 439 exp = convert (ptr_type_node, exp); 440 441 *slot = tree_cons (type, exp, NULL_TREE); 442 443 return exp; 444} 445 446int 447expand_catch_class (treetreehash_entry **entry, int) 448{ 449 struct treetreehash_entry *ite = *entry; 450 tree addr = TREE_VALUE ((tree)ite->value); 451 tree decl; 452 STRIP_NOPS (addr); 453 decl = TREE_OPERAND (addr, 0); 454 rest_of_decl_compilation (decl, global_bindings_p (), 0); 455 return true; 456} 457 458/* For every class in the TYPE_TO_RUNTIME_MAP, expand the 459 corresponding object that is used by the runtime type matcher. */ 460 461void 462java_expand_catch_classes (tree this_class) 463{ 464 if (TYPE_TO_RUNTIME_MAP (this_class)) 465 TYPE_TO_RUNTIME_MAP (this_class)->traverse<int, expand_catch_class> (0); 466} 467 468/* Build and push the variable that will hold the exception object 469 within this function. */ 470 471static tree 472build_exception_object_var (void) 473{ 474 tree decl = DECL_FUNCTION_EXC_OBJ (current_function_decl); 475 if (decl == NULL) 476 { 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; 481 482 DECL_FUNCTION_EXC_OBJ (current_function_decl) = decl; 483 pushdecl_function_level (decl); 484 } 485 return decl; 486} 487 488/* Build a reference to the jthrowable object being carried in the 489 exception header. */ 490 491tree 492build_exception_object_ref (tree type) 493{ 494 tree obj; 495 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); 504 505 return obj; 506} 507 508/* If there are any handlers for this range, issue end of range, 509 and then all handler blocks */ 510void 511expand_end_java_handler (struct eh_range *range) 512{ 513 tree handler = range->handlers; 514 if (handler) 515 { 516 tree exc_obj = build_exception_object_var (); 517 tree catches = make_node (STATEMENT_LIST); 518 tree_stmt_iterator catches_i = tsi_last (catches); 519 tree *body; 520 521 for (; handler; handler = TREE_CHAIN (handler)) 522 { 523 tree type, eh_type, x; 524 tree stmts = make_node (STATEMENT_LIST); 525 tree_stmt_iterator stmts_i = tsi_last (stmts); 526 527 type = TREE_PURPOSE (handler); 528 if (type == NULL) 529 type = throwable_type_node; 530 eh_type = prepare_eh_table_type (type); 531 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); 536 537 x = build1 (GOTO_EXPR, void_type_node, TREE_VALUE (handler)); 538 tsi_link_after (&stmts_i, x, TSI_CONTINUE_LINKING); 539 540 x = build2 (CATCH_EXPR, void_type_node, eh_type, stmts); 541 tsi_link_after (&catches_i, x, TSI_CONTINUE_LINKING); 542 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 547 for the catch. */ 548 if (type == throwable_type_node) 549 break; 550 } 551 552 body = get_stmts (); 553 *body = build2 (TRY_CATCH_EXPR, void_type_node, *body, catches); 554 } 555 556#if defined(DEBUG_JAVA_BINDING_LEVELS) 557 indent (); 558 fprintf (stderr, "expand end handler pc %d <-- %d\n", 559 current_pc, range->start_pc); 560#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */ 561} 562 563/* Recursive helper routine for maybe_start_handlers. */ 564 565static void 566check_start_handlers (struct eh_range *range, int pc) 567{ 568 if (range != NULL_EH_RANGE && range->start_pc == pc) 569 { 570 check_start_handlers (range->outer, pc); 571 if (!range->expanded) 572 expand_start_java_handler (range); 573 } 574} 575 576 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. 580 581 This is used to ensure that -fexceptions has been specified if the 582 compiler tries to use any exception-specific functions. */ 583 584static inline int 585doing_eh (void) 586{ 587 if (! flag_exceptions) 588 { 589 static int warned = 0; 590 if (! warned) 591 { 592 error ("exception handling disabled, use -fexceptions to enable"); 593 warned = 1; 594 } 595 return 0; 596 } 597 return 1; 598} 599 600static struct eh_range *current_range; 601 602/* Emit any start-of-try-range starting at start_pc and ending after 603 end_pc. */ 604 605void 606maybe_start_try (int start_pc, int end_pc) 607{ 608 struct eh_range *range; 609 if (! doing_eh ()) 610 return; 611 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; 616 617 current_range = range; 618 check_start_handlers (range, start_pc); 619} 620 621