OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / java / except.c
1 /* Handle exceptions for GNU compiler for the Java(TM) language.
2    Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005,
3    2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
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
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.
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 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "tree.h"
30 #include "java-tree.h"
31 #include "javaop.h"
32 #include "java-opcodes.h"
33 #include "jcf.h"
34 #include "java-except.h"
35 #include "diagnostic-core.h"
36 #include "toplev.h"
37 #include "tree-iterator.h"
38
39
40 static void expand_start_java_handler (struct eh_range *);
41 static struct eh_range *find_handler_in_range (int, struct eh_range *,
42                                                struct eh_range *);
43 static void check_start_handlers (struct eh_range *, int);
44 static void free_eh_ranges (struct eh_range *range);
45
46 struct eh_range *current_method_handlers;
47
48 struct eh_range *current_try_block = NULL;
49
50 /* These variables are used to speed up find_handler. */
51
52 static int cache_range_start, cache_range_end;
53 static struct eh_range *cache_range;
54 static struct eh_range *cache_next_child;
55
56 /* A dummy range that represents the entire method. */
57
58 struct eh_range whole_range;
59
60 /* Check the invariants of the structure we're using to contain
61    exception regions.  Either returns true or fails an assertion
62    check.  */
63
64 bool
65 sanity_check_exception_range (struct eh_range *range)
66 {
67   struct eh_range *ptr = range->first_child;
68   for (; ptr; ptr = ptr->next_sibling)
69     {
70       gcc_assert (ptr->outer == range
71                   && ptr->end_pc > ptr->start_pc);
72       if (ptr->next_sibling)
73         gcc_assert (ptr->next_sibling->start_pc >= ptr->end_pc);
74       gcc_assert (ptr->start_pc >= ptr->outer->start_pc
75                   && ptr->end_pc <=  ptr->outer->end_pc);
76       (void) sanity_check_exception_range (ptr);
77     }
78   return true;
79 }
80
81 #if defined(DEBUG_JAVA_BINDING_LEVELS)
82 extern int is_class_level;
83 extern int current_pc;
84 extern int binding_depth;
85 extern void indent (void);
86 static void
87 print_ranges (struct eh_range *range)
88 {
89   if (! range)
90     return;
91
92   struct eh_range *child = range->first_child;
93   
94   indent ();
95   fprintf (stderr, "handler pc %d --> %d ", range->start_pc, range->end_pc);
96   
97   tree handler = range->handlers;
98   for ( ; handler != NULL_TREE; handler = TREE_CHAIN (handler))
99     {
100       tree type = TREE_PURPOSE (handler);
101       if (type == NULL)
102         type = throwable_type_node;
103       fprintf (stderr, " type=%s ", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
104     }
105   fprintf (stderr, "\n");
106
107   int saved = binding_depth;
108   binding_depth++;
109   print_ranges (child);
110   binding_depth = saved;
111
112   print_ranges (range->next_sibling);
113 }
114 #endif
115
116 /* Search for the most specific eh_range containing PC.
117    Assume PC is within RANGE.
118    CHILD is a list of children of RANGE such that any
119    previous children have end_pc values that are too low. */
120
121 static struct eh_range *
122 find_handler_in_range (int pc, struct eh_range *range, struct eh_range *child)
123 {
124   for (; child != NULL;  child = child->next_sibling)
125     {
126       if (pc < child->start_pc)
127         break;
128       if (pc < child->end_pc)
129         return find_handler_in_range (pc, child, child->first_child);
130     }
131   cache_range = range;
132   cache_range_start = pc;
133   cache_next_child = child;
134   cache_range_end = child == NULL ? range->end_pc : child->start_pc;
135   return range;
136 }
137
138 /* Find the inner-most handler that contains PC. */
139
140 struct eh_range *
141 find_handler (int pc)
142 {
143   struct eh_range *h;
144   if (pc >= cache_range_start)
145     {
146       h = cache_range;
147       if (pc < cache_range_end)
148         return h;
149       while (pc >= h->end_pc)
150         {
151           cache_next_child = h->next_sibling;
152           h = h->outer;
153         }
154     }
155   else
156     {
157       h = &whole_range;
158       cache_next_child = h->first_child;
159     }
160   return find_handler_in_range (pc, h, cache_next_child);
161 }
162
163 static void
164 free_eh_ranges (struct eh_range *range)
165 {
166   while (range) 
167     {
168       struct eh_range *next = range->next_sibling;
169       free_eh_ranges (range->first_child);
170       if (range != &whole_range)
171         free (range);
172       range = next;
173     }
174 }
175
176 /* Called to re-initialize the exception machinery for a new method. */
177
178 void
179 method_init_exceptions (void)
180 {
181   free_eh_ranges (&whole_range);
182   whole_range.start_pc = 0;
183   whole_range.end_pc = DECL_CODE_LENGTH (current_function_decl) + 1;
184   whole_range.outer = NULL;
185   whole_range.first_child = NULL;
186   whole_range.next_sibling = NULL;
187   cache_range_start = 0xFFFFFF;
188 }
189
190 /* Split an exception range into two at PC.  The sub-ranges that
191    belong to the range are split and distributed between the two new
192    ranges.  */
193
194 static void
195 split_range (struct eh_range *range, int pc)
196 {
197   struct eh_range *ptr;
198   struct eh_range **first_child, **second_child;
199   struct eh_range *h;
200
201   /* First, split all the sub-ranges.  */
202   for (ptr = range->first_child; ptr; ptr = ptr->next_sibling)
203     {
204       if (pc > ptr->start_pc
205           && pc < ptr->end_pc)
206         {
207           split_range (ptr, pc);
208         }
209     }
210
211   /* Create a new range.  */
212   h = XNEW (struct eh_range);
213
214   h->start_pc = pc;
215   h->end_pc = range->end_pc;
216   h->next_sibling = range->next_sibling;
217   range->next_sibling = h;
218   range->end_pc = pc;
219   h->handlers = build_tree_list (TREE_PURPOSE (range->handlers),
220                                  TREE_VALUE (range->handlers));
221   h->next_sibling = NULL;
222   h->expanded = 0;
223   h->stmt = NULL;
224   h->outer = range->outer;
225   h->first_child = NULL;
226
227   ptr = range->first_child;
228   first_child = &range->first_child;
229   second_child = &h->first_child;
230
231   /* Distribute the sub-ranges between the two new ranges.  */
232   for (ptr = range->first_child; ptr; ptr = ptr->next_sibling)
233     {
234       if (ptr->start_pc < pc)
235         {
236           *first_child = ptr;
237           ptr->outer = range;
238           first_child = &ptr->next_sibling;
239         }
240       else
241         {
242           *second_child = ptr;
243           ptr->outer = h;
244           second_child = &ptr->next_sibling;
245         }
246     }
247   *first_child = NULL;
248   *second_child = NULL;
249 }  
250
251
252 /* Add an exception range. 
253
254    There are some missed optimization opportunities here.  For
255    example, some bytecode obfuscators generate seemingly
256    nonoverlapping exception ranges which, when coalesced, do in fact
257    nest correctly.  We could merge these, but we'd have to fix up all
258    the enclosed regions first and perhaps create a new range anyway if
259    it overlapped existing ranges.
260    
261    Also, we don't attempt to detect the case where two previously
262    added disjoint ranges could be coalesced by a new range.  */
263
264 void 
265 add_handler (int start_pc, int end_pc, tree handler, tree type)
266 {
267   struct eh_range *ptr, *h;
268   struct eh_range **first_child, **prev;
269
270   /* First, split all the existing ranges that we need to enclose.  */
271   for (ptr = whole_range.first_child; ptr; ptr = ptr->next_sibling)
272     {
273       if (start_pc > ptr->start_pc
274           && start_pc < ptr->end_pc)
275         {
276           split_range (ptr, start_pc);
277         }
278
279       if (end_pc > ptr->start_pc
280           && end_pc < ptr->end_pc)
281         {
282           split_range (ptr, end_pc);
283         }
284
285       if (ptr->start_pc >= end_pc)
286         break;
287     }
288
289   /* Create the new range.  */
290   h = XNEW (struct eh_range);
291   first_child = &h->first_child;
292
293   h->start_pc = start_pc;
294   h->end_pc = end_pc;
295   h->first_child = NULL;
296   h->outer = NULL_EH_RANGE;
297   h->handlers = build_tree_list (type, handler);
298   h->next_sibling = NULL;
299   h->expanded = 0;
300   h->stmt = NULL;
301
302   /* Find every range at the top level that will be a sub-range of the
303      range we're inserting and make it so.  */
304   {
305     struct eh_range **prev = &whole_range.first_child;
306     for (ptr = *prev; ptr;)
307       {
308         struct eh_range *next = ptr->next_sibling;
309
310         if (ptr->start_pc >= end_pc)
311           break;
312
313         if (ptr->start_pc < start_pc)
314           {
315             prev = &ptr->next_sibling;
316           }
317         else if (ptr->start_pc >= start_pc
318                  && ptr->start_pc < end_pc)
319           {
320             *prev = next;
321             *first_child = ptr;
322             first_child = &ptr->next_sibling;
323             ptr->outer = h;
324             ptr->next_sibling = NULL;     
325           }
326
327         ptr = next;
328       }
329   }
330
331   /* Find the right place to insert the new range.  */
332   prev = &whole_range.first_child;
333   for (ptr = *prev; ptr; prev = &ptr->next_sibling, ptr = ptr->next_sibling)
334     {
335       gcc_assert (ptr->outer == NULL_EH_RANGE);
336       if (ptr->start_pc >= start_pc)
337         break;
338     }
339
340   /* And insert it there.  */
341   *prev = h;
342   if (ptr)
343     {
344       h->next_sibling = ptr;
345       h->outer = ptr->outer;
346     }
347 }
348       
349   
350 /* if there are any handlers for this range, issue start of region */
351 static void
352 expand_start_java_handler (struct eh_range *range)
353 {
354 #if defined(DEBUG_JAVA_BINDING_LEVELS)
355   indent ();
356   fprintf (stderr, "expand start handler pc %d --> %d\n",
357            current_pc, range->end_pc);
358 #endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
359   pushlevel (0);
360   register_exception_range (range,  range->start_pc, range->end_pc);
361   range->expanded = 1;
362 }
363
364 tree
365 prepare_eh_table_type (tree type)
366 {
367   tree exp;
368   tree *slot;
369   const char *name;
370   char *buf;
371   tree decl;
372   tree utf8_ref;
373
374   /* The "type" (match_info) in a (Java) exception table is a pointer to:
375    * a) NULL - meaning match any type in a try-finally.
376    * b) a pointer to a pointer to a class.
377    * c) a pointer to a pointer to a utf8_ref.  The pointer is
378    * rewritten to point to the appropriate class.  */
379
380   if (type == NULL_TREE)
381     return NULL_TREE;
382
383   if (TYPE_TO_RUNTIME_MAP (output_class) == NULL)
384     TYPE_TO_RUNTIME_MAP (output_class) = java_treetreehash_create (10);
385   
386   slot = java_treetreehash_new (TYPE_TO_RUNTIME_MAP (output_class), type);
387   if (*slot != NULL)
388     return TREE_VALUE (*slot);
389
390   if (is_compiled_class (type) && !flag_indirect_dispatch)
391     {
392       name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
393       buf = (char *) alloca (strlen (name) + 5);
394       sprintf (buf, "%s_ref", name);
395       decl = build_decl (input_location,
396                          VAR_DECL, get_identifier (buf), ptr_type_node);
397       TREE_STATIC (decl) = 1;
398       DECL_ARTIFICIAL (decl) = 1;
399       DECL_IGNORED_P (decl) = 1;
400       TREE_READONLY (decl) = 1;
401       TREE_THIS_VOLATILE (decl) = 0;
402       DECL_INITIAL (decl) = build_class_ref (type);
403       layout_decl (decl, 0);
404       pushdecl (decl);
405       exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (decl)), decl);
406     }
407   else
408     {
409       utf8_ref = build_utf8_ref (DECL_NAME (TYPE_NAME (type)));
410       name = IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (utf8_ref, 0)));
411       buf = (char *) alloca (strlen (name) + 5);
412       sprintf (buf, "%s_ref", name);
413       decl = build_decl (input_location,
414                          VAR_DECL, get_identifier (buf), utf8const_ptr_type);
415       TREE_STATIC (decl) = 1;
416       DECL_ARTIFICIAL (decl) = 1;
417       DECL_IGNORED_P (decl) = 1;
418       TREE_READONLY (decl) = 1;
419       TREE_THIS_VOLATILE (decl) = 0;
420       layout_decl (decl, 0);
421       pushdecl (decl);
422       exp = build1 (ADDR_EXPR, build_pointer_type (utf8const_ptr_type), decl);
423       CONSTRUCTOR_APPEND_ELT (TYPE_CATCH_CLASSES (output_class),
424                               NULL_TREE,
425                               make_catch_class_record (exp, utf8_ref));
426     }
427
428   exp = convert (ptr_type_node, exp);
429
430   *slot = tree_cons (type, exp, NULL_TREE);
431
432   return exp;
433 }
434
435 static int
436 expand_catch_class (void **entry, void *x ATTRIBUTE_UNUSED)
437 {
438   struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry;
439   tree addr = TREE_VALUE ((tree)ite->value);
440   tree decl;
441   STRIP_NOPS (addr);
442   decl = TREE_OPERAND (addr, 0);
443   rest_of_decl_compilation (decl, global_bindings_p (), 0);
444   return true;
445 }
446   
447 /* For every class in the TYPE_TO_RUNTIME_MAP, expand the
448    corresponding object that is used by the runtime type matcher.  */
449
450 void
451 java_expand_catch_classes (tree this_class)
452 {
453   if (TYPE_TO_RUNTIME_MAP (this_class))
454     htab_traverse 
455       (TYPE_TO_RUNTIME_MAP (this_class),
456        expand_catch_class, NULL);
457 }
458
459 /* Build and push the variable that will hold the exception object
460    within this function.  */
461
462 static tree
463 build_exception_object_var (void)
464 {
465   tree decl = DECL_FUNCTION_EXC_OBJ (current_function_decl);
466   if (decl == NULL)
467     {
468       decl = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
469                          VAR_DECL, get_identifier ("#exc_obj"), ptr_type_node);
470       DECL_IGNORED_P (decl) = 1;
471       DECL_ARTIFICIAL (decl) = 1;
472
473       DECL_FUNCTION_EXC_OBJ (current_function_decl) = decl;
474       pushdecl_function_level (decl);
475     }
476   return decl;
477 }
478
479 /* Build a reference to the jthrowable object being carried in the
480    exception header.  */
481
482 tree
483 build_exception_object_ref (tree type)
484 {
485   tree obj;
486
487   /* Java only passes object via pointer and doesn't require adjusting.
488      The java object is immediately before the generic exception header.  */
489   obj = build_exception_object_var ();
490   obj = fold_convert (build_pointer_type (type), obj);
491   obj = fold_build_pointer_plus (obj,
492                 fold_build1 (NEGATE_EXPR, sizetype,
493                              TYPE_SIZE_UNIT (TREE_TYPE (obj))));
494   obj = build1 (INDIRECT_REF, type, obj);
495
496   return obj;
497 }
498
499 /* If there are any handlers for this range, issue end of range,
500    and then all handler blocks */
501 void
502 expand_end_java_handler (struct eh_range *range)
503 {  
504   tree handler = range->handlers;
505   if (handler)
506     {
507       tree exc_obj = build_exception_object_var ();
508       tree catches = make_node (STATEMENT_LIST);
509       tree_stmt_iterator catches_i = tsi_last (catches);
510       tree *body;
511
512       for (; handler; handler = TREE_CHAIN (handler))
513         {
514           tree type, eh_type, x;
515           tree stmts = make_node (STATEMENT_LIST);
516           tree_stmt_iterator stmts_i = tsi_last (stmts);
517
518           type = TREE_PURPOSE (handler);
519           if (type == NULL)
520             type = throwable_type_node;
521           eh_type = prepare_eh_table_type (type);
522
523           x = build_call_expr (builtin_decl_explicit (BUILT_IN_EH_POINTER),
524                                1, integer_zero_node);
525           x = build2 (MODIFY_EXPR, void_type_node, exc_obj, x);
526           tsi_link_after (&stmts_i, x, TSI_CONTINUE_LINKING);
527
528           x = build1 (GOTO_EXPR, void_type_node, TREE_VALUE (handler));
529           tsi_link_after (&stmts_i, x, TSI_CONTINUE_LINKING);
530
531           x = build2 (CATCH_EXPR, void_type_node, eh_type, stmts);
532           tsi_link_after (&catches_i, x, TSI_CONTINUE_LINKING);
533
534           /* Throwable can match anything in Java, and therefore
535              any subsequent handlers are unreachable.  */
536           /* ??? If we're assured of no foreign language exceptions,
537              we'd be better off using NULL as the exception type
538              for the catch.  */
539           if (type == throwable_type_node)
540             break;
541         }
542
543       body = get_stmts ();
544       *body = build2 (TRY_CATCH_EXPR, void_type_node, *body, catches);
545     }
546
547 #if defined(DEBUG_JAVA_BINDING_LEVELS)
548   indent ();
549   fprintf (stderr, "expand end handler pc %d <-- %d\n",
550            current_pc, range->start_pc);
551 #endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
552 }
553
554 /* Recursive helper routine for maybe_start_handlers. */
555
556 static void
557 check_start_handlers (struct eh_range *range, int pc)
558 {
559   if (range != NULL_EH_RANGE && range->start_pc == pc)
560     {
561       check_start_handlers (range->outer, pc);
562       if (!range->expanded)
563         expand_start_java_handler (range);
564     }
565 }
566
567
568 /* Routine to see if exception handling is turned on.
569    DO_WARN is nonzero if we want to inform the user that exception
570    handling is turned off.
571
572    This is used to ensure that -fexceptions has been specified if the
573    compiler tries to use any exception-specific functions.  */
574
575 static inline int
576 doing_eh (void)
577 {
578   if (! flag_exceptions)
579     {
580       static int warned = 0;
581       if (! warned)
582         {
583           error ("exception handling disabled, use -fexceptions to enable");
584           warned = 1;
585         }
586       return 0;
587     }
588   return 1;
589 }
590
591 static struct eh_range *current_range;
592
593 /* Emit any start-of-try-range starting at start_pc and ending after
594    end_pc. */
595
596 void
597 maybe_start_try (int start_pc, int end_pc)
598 {
599   struct eh_range *range;
600   if (! doing_eh ())
601     return;
602
603   range = find_handler (start_pc);
604   while (range != NULL_EH_RANGE && range->start_pc == start_pc
605          && range->end_pc < end_pc)
606     range = range->outer;
607          
608   current_range = range;
609   check_start_handlers (range, start_pc);
610 }
611