]> gcc.gnu.org Git - gcc.git/blame - gcc/java/except.c
java-tree.h (throw_node): Define as a single member of java_global_trees instead...
[gcc.git] / gcc / java / except.c
CommitLineData
e04a16fb 1/* Handle exceptions for GNU compiler for the Java(TM) language.
3852e8af 2 Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
e04a16fb
AG
3
4This file is part of GNU CC.
5
6GNU CC 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 2, or (at your option)
9any later version.
10
11GNU CC 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 GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.
20
21Java and all Java-based marks are trademarks or registered trademarks
22of Sun Microsystems, Inc. in the United States and other countries.
23The Free Software Foundation is independent of Sun Microsystems, Inc. */
24
e04a16fb 25#include "config.h"
1f43f4b4 26#include "system.h"
e04a16fb
AG
27#include "tree.h"
28#include "real.h"
29#include "rtl.h"
30#include "java-tree.h"
31#include "javaop.h"
32#include "java-opcodes.h"
33#include "jcf.h"
b384405b 34#include "function.h"
e04a16fb
AG
35#include "except.h"
36#include "java-except.h"
37#include "eh-common.h"
1f43f4b4 38#include "toplev.h"
e04a16fb 39
df32d2ce
KG
40static void expand_start_java_handler PARAMS ((struct eh_range *));
41static void expand_end_java_handler PARAMS ((struct eh_range *));
42static struct eh_range *find_handler_in_range PARAMS ((int, struct eh_range *,
c8e7d2e6 43 struct eh_range *));
df32d2ce 44static void link_handler PARAMS ((struct eh_range *, struct eh_range *));
ae0a06c5 45static void check_start_handlers PARAMS ((struct eh_range *, int));
1f8f4a0b 46static void free_eh_ranges PARAMS ((struct eh_range *range));
4bcde32e 47
e04a16fb
AG
48extern struct obstack permanent_obstack;
49
50struct eh_range *current_method_handlers;
51
52struct eh_range *current_try_block = NULL;
53
54struct eh_range *eh_range_freelist = NULL;
55
56/* These variables are used to speed up find_handler. */
57
58static int cache_range_start, cache_range_end;
59static struct eh_range *cache_range;
60static struct eh_range *cache_next_child;
61
62/* A dummy range that represents the entire method. */
63
64struct eh_range whole_range;
65
e8b22dd1
AH
66#if defined(DEBUG_JAVA_BINDING_LEVELS)
67int binding_depth;
68int is_class_level;
69int current_pc;
70extern void indent ();
71
72#endif
73
e04a16fb
AG
74/* Search for the most specific eh_range containing PC.
75 Assume PC is within RANGE.
76 CHILD is a list of children of RANGE such that any
77 previous children have end_pc values that are too low. */
78
79static struct eh_range *
80find_handler_in_range (pc, range, child)
81 int pc;
82 struct eh_range *range;
83 register struct eh_range *child;
84{
85 for (; child != NULL; child = child->next_sibling)
86 {
87 if (pc < child->start_pc)
88 break;
44d7502b 89 if (pc < child->end_pc)
e04a16fb
AG
90 return find_handler_in_range (pc, child, child->first_child);
91 }
92 cache_range = range;
93 cache_range_start = pc;
94 cache_next_child = child;
95 cache_range_end = child == NULL ? range->end_pc : child->start_pc;
96 return range;
97}
98
99/* Find the inner-most handler that contains PC. */
100
101struct eh_range *
102find_handler (pc)
103 int pc;
104{
105 struct eh_range *h;
106 if (pc >= cache_range_start)
107 {
108 h = cache_range;
109 if (pc < cache_range_end)
110 return h;
111 while (pc >= h->end_pc)
112 {
113 cache_next_child = h->next_sibling;
114 h = h->outer;
115 }
116 }
117 else
118 {
119 h = &whole_range;
120 cache_next_child = h->first_child;
121 }
122 return find_handler_in_range (pc, h, cache_next_child);
123}
124
5a9e5c6f 125/* Recursive helper routine for check_nested_ranges. */
e04a16fb 126
5a9e5c6f
TT
127static void
128link_handler (range, outer)
129 struct eh_range *range, *outer;
e04a16fb
AG
130{
131 struct eh_range **ptr;
5a9e5c6f
TT
132
133 if (range->start_pc == outer->start_pc && range->end_pc == outer->end_pc)
134 {
99fd3aa5 135 outer->handlers = chainon (outer->handlers, range->handlers);
5a9e5c6f
TT
136 return;
137 }
138
139 /* If the new range completely encloses the `outer' range, then insert it
140 between the outer range and its parent. */
141 if (range->start_pc <= outer->start_pc && range->end_pc >= outer->end_pc)
142 {
143 range->outer = outer->outer;
144 range->next_sibling = NULL;
145 range->first_child = outer;
44d7502b
AH
146 {
147 struct eh_range **pr = &(outer->outer->first_child);
148 while (*pr != outer)
149 pr = &(*pr)->next_sibling;
150 *pr = range;
151 }
5a9e5c6f
TT
152 outer->outer = range;
153 return;
154 }
155
156 /* Handle overlapping ranges by splitting the new range. */
157 if (range->start_pc < outer->start_pc || range->end_pc > outer->end_pc)
e04a16fb 158 {
5a9e5c6f 159 struct eh_range *h
1f8f4a0b 160 = (struct eh_range *) xmalloc (sizeof (struct eh_range));
5a9e5c6f
TT
161 if (range->start_pc < outer->start_pc)
162 {
163 h->start_pc = range->start_pc;
164 h->end_pc = outer->start_pc;
165 range->start_pc = outer->start_pc;
166 }
167 else
168 {
169 h->start_pc = outer->end_pc;
170 h->end_pc = range->end_pc;
171 range->end_pc = outer->end_pc;
172 }
173 h->first_child = NULL;
174 h->outer = NULL;
175 h->handlers = build_tree_list (TREE_PURPOSE (range->handlers),
176 TREE_VALUE (range->handlers));
177 h->next_sibling = NULL;
178 /* Restart both from the top to avoid having to make this
179 function smart about reentrancy. */
180 link_handler (h, &whole_range);
181 link_handler (range, &whole_range);
182 return;
e04a16fb 183 }
5a9e5c6f 184
e04a16fb
AG
185 ptr = &outer->first_child;
186 for (;; ptr = &(*ptr)->next_sibling)
187 {
5a9e5c6f 188 if (*ptr == NULL || range->end_pc <= (*ptr)->start_pc)
e04a16fb 189 {
5a9e5c6f
TT
190 range->next_sibling = *ptr;
191 range->first_child = NULL;
192 range->outer = outer;
193 *ptr = range;
194 return;
195 }
196 else if (range->start_pc < (*ptr)->end_pc)
197 {
198 link_handler (range, *ptr);
199 return;
e04a16fb 200 }
e04a16fb
AG
201 /* end_pc > (*ptr)->start_pc && start_pc >= (*ptr)->end_pc. */
202 }
203}
204
5a9e5c6f
TT
205/* The first pass of exception range processing (calling add_handler)
206 constructs a linked list of exception ranges. We turn this into
207 the data structure expected by the rest of the code, and also
208 ensure that exception ranges are properly nested. */
209
210void
211handle_nested_ranges ()
212{
213 struct eh_range *ptr, *next;
214
215 ptr = whole_range.first_child;
216 whole_range.first_child = NULL;
217 for (; ptr; ptr = next)
218 {
219 next = ptr->next_sibling;
220 ptr->next_sibling = NULL;
221 link_handler (ptr, &whole_range);
222 }
223}
224
1f8f4a0b
MM
225/* Free RANGE as well as its children and siblings. */
226
227static void
228free_eh_ranges (range)
229 struct eh_range *range;
230{
231 while (range)
232 {
233 struct eh_range *next = range->next_sibling;
234 free_eh_ranges (range->first_child);
1a2ebe6d
APB
235 if (range != &whole_range)
236 free (range);
1f8f4a0b
MM
237 range = next;
238 }
239}
5a9e5c6f 240
e04a16fb
AG
241/* Called to re-initialize the exception machinery for a new method. */
242
243void
244method_init_exceptions ()
245{
1f8f4a0b 246 free_eh_ranges (&whole_range);
e04a16fb
AG
247 whole_range.start_pc = 0;
248 whole_range.end_pc = DECL_CODE_LENGTH (current_function_decl) + 1;
249 whole_range.outer = NULL;
250 whole_range.first_child = NULL;
251 whole_range.next_sibling = NULL;
252 cache_range_start = 0xFFFFFF;
e4de5a10
PB
253 java_set_exception_lang_code ();
254}
255
256void
257java_set_exception_lang_code ()
258{
e04a16fb
AG
259 set_exception_lang_code (EH_LANG_Java);
260 set_exception_version_code (1);
261}
262
5a9e5c6f
TT
263/* Add an exception range. If we already have an exception range
264 which has the same handler and label, and the new range overlaps
265 that one, then we simply extend the existing range. Some bytecode
266 obfuscators generate seemingly nonoverlapping exception ranges
267 which, when coalesced, do in fact nest correctly.
268
269 This constructs an ordinary linked list which check_nested_ranges()
270 later turns into the data structure we actually want.
271
272 We expect the input to come in order of increasing START_PC. This
273 function doesn't attempt to detect the case where two previously
274 added disjoint ranges could be coalesced by a new range; that is
275 what the sorting counteracts. */
276
277void
e04a16fb
AG
278add_handler (start_pc, end_pc, handler, type)
279 int start_pc, end_pc;
280 tree handler;
281 tree type;
282{
5a9e5c6f
TT
283 struct eh_range *ptr, *prev = NULL, *h;
284
285 for (ptr = whole_range.first_child; ptr; ptr = ptr->next_sibling)
286 {
287 if (start_pc >= ptr->start_pc
288 && start_pc <= ptr->end_pc
289 && TREE_PURPOSE (ptr->handlers) == type
290 && TREE_VALUE (ptr->handlers) == handler)
291 {
292 /* Already found an overlapping range, so coalesce. */
293 ptr->end_pc = MAX (ptr->end_pc, end_pc);
294 return;
295 }
296 prev = ptr;
297 }
298
1f8f4a0b 299 h = (struct eh_range *) xmalloc (sizeof (struct eh_range));
5a9e5c6f
TT
300 h->start_pc = start_pc;
301 h->end_pc = end_pc;
302 h->first_child = NULL;
303 h->outer = NULL;
304 h->handlers = build_tree_list (type, handler);
305 h->next_sibling = NULL;
e8b22dd1 306 h->expanded = 0;
5a9e5c6f
TT
307
308 if (prev == NULL)
309 whole_range.first_child = h;
310 else
311 prev->next_sibling = h;
e04a16fb
AG
312}
313
314
315/* if there are any handlers for this range, issue start of region */
4bcde32e 316static void
e04a16fb 317expand_start_java_handler (range)
e8b22dd1 318 struct eh_range *range;
e04a16fb 319{
e8b22dd1
AH
320#if defined(DEBUG_JAVA_BINDING_LEVELS)
321 indent ();
322 fprintf (stderr, "expand start handler pc %d --> %d\n",
323 current_pc, range->end_pc);
324#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
325 range->expanded = 1;
e04a16fb
AG
326 expand_eh_region_start ();
327}
328
e4de5a10
PB
329tree
330prepare_eh_table_type (type)
331 tree type;
332{
333 tree exp;
334
335 /* The "type" (metch_info) in a (Java) exception table is one:
336 * a) NULL - meaning match any type in a try-finally.
337 * b) a pointer to a (ccmpiled) class (low-order bit 0).
338 * c) a pointer to the Utf8Const name of the class, plus one
339 * (which yields a value with low-order bit 1). */
340
e4de5a10 341 if (type == NULL_TREE)
9a7ab4b3 342 exp = CATCH_ALL_TYPE;
e4de5a10
PB
343 else if (is_compiled_class (type))
344 exp = build_class_ref (type);
345 else
346 exp = fold (build
347 (PLUS_EXPR, ptr_type_node,
348 build_utf8_ref (build_internal_class_name (type)),
349 size_one_node));
e4de5a10
PB
350 return exp;
351}
352
e04a16fb
AG
353/* if there are any handlers for this range, isssue end of range,
354 and then all handler blocks */
4bcde32e 355static void
e04a16fb
AG
356expand_end_java_handler (range)
357 struct eh_range *range;
e8b22dd1 358{
e04a16fb 359 tree handler = range->handlers;
e8b22dd1 360 force_poplevels (range->start_pc);
e04a16fb
AG
361 expand_start_all_catch ();
362 for ( ; handler != NULL_TREE; handler = TREE_CHAIN (handler))
363 {
e4de5a10
PB
364 start_catch_handler (prepare_eh_table_type (TREE_PURPOSE (handler)));
365 /* Push the thrown object on the top of the stack */
e04a16fb 366 expand_goto (TREE_VALUE (handler));
0974e9fe
APB
367 expand_resume_after_catch ();
368 end_catch_handler ();
e04a16fb
AG
369 }
370 expand_end_all_catch ();
e8b22dd1
AH
371#if defined(DEBUG_JAVA_BINDING_LEVELS)
372 indent ();
373 fprintf (stderr, "expand end handler pc %d <-- %d\n",
374 current_pc, range->start_pc);
375#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
e04a16fb
AG
376}
377
378/* Recursive helper routine for maybe_start_handlers. */
379
380static void
381check_start_handlers (range, pc)
382 struct eh_range *range;
383 int pc;
384{
385 if (range != NULL_EH_RANGE && range->start_pc == pc)
386 {
387 check_start_handlers (range->outer, pc);
e8b22dd1
AH
388 if (!range->expanded)
389 expand_start_java_handler (range);
e04a16fb
AG
390 }
391}
392
e04a16fb 393
e8b22dd1
AH
394static struct eh_range *current_range;
395
396/* Emit any start-of-try-range starting at start_pc and ending after
397 end_pc. */
e04a16fb
AG
398
399void
e8b22dd1
AH
400maybe_start_try (start_pc, end_pc)
401 int start_pc;
402 int end_pc;
e04a16fb 403{
e8b22dd1 404 struct eh_range *range;
e04a16fb
AG
405 if (! doing_eh (1))
406 return;
407
e8b22dd1
AH
408 range = find_handler (start_pc);
409 while (range != NULL_EH_RANGE && range->start_pc == start_pc
410 && range->end_pc < end_pc)
411 range = range->outer;
412
413 current_range = range;
ef86eabb 414 check_start_handlers (range, start_pc);
e04a16fb
AG
415}
416
e8b22dd1
AH
417/* Emit any end-of-try-range ending at end_pc and starting before
418 start_pc. */
e04a16fb
AG
419
420void
e8b22dd1
AH
421maybe_end_try (start_pc, end_pc)
422 int start_pc;
423 int end_pc;
e04a16fb
AG
424{
425 if (! doing_eh (1))
426 return;
427
e8b22dd1
AH
428 while (current_range != NULL_EH_RANGE && current_range->end_pc <= end_pc
429 && current_range->start_pc >= start_pc)
e04a16fb
AG
430 {
431 expand_end_java_handler (current_range);
432 current_range = current_range->outer;
433 }
434}
435
436/* Emit the handler labels and their code */
437
438void
439emit_handlers ()
440{
441 if (catch_clauses)
442 {
443 rtx funcend = gen_label_rtx ();
444 emit_jump (funcend);
445
446 emit_insns (catch_clauses);
c14f7160 447 catch_clauses = catch_clauses_last = NULL_RTX;
e04a16fb
AG
448 expand_leftover_cleanups ();
449
450 emit_label (funcend);
451 }
452}
1b18747f
AH
453
454/* Resume executing at the statement immediately after the end of an
455 exception region. */
456
457void
458expand_resume_after_catch ()
459{
460 expand_goto (top_label_entry (&caught_return_label_stack));
461}
This page took 0.632182 seconds and 5 git commands to generate.