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