1 /* Handle exceptions for GNU compiler for the Java(TM) language.
2 Copyright (C) 1997 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC 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 2, or (at your option)
11 GNU CC 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 GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
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. */
30 #include "java-tree.h"
32 #include "java-opcodes.h"
35 #include "java-except.h"
36 #include "eh-common.h"
39 extern struct obstack permanent_obstack
;
41 struct eh_range
*current_method_handlers
;
43 struct eh_range
*current_try_block
= NULL
;
45 struct eh_range
*eh_range_freelist
= NULL
;
47 /* These variables are used to speed up find_handler. */
49 static int cache_range_start
, cache_range_end
;
50 static struct eh_range
*cache_range
;
51 static struct eh_range
*cache_next_child
;
53 /* A dummy range that represents the entire method. */
55 struct eh_range whole_range
;
57 /* Search for the most specific eh_range containing PC.
58 Assume PC is within RANGE.
59 CHILD is a list of children of RANGE such that any
60 previous children have end_pc values that are too low. */
62 static struct eh_range
*
63 find_handler_in_range (pc
, range
, child
)
65 struct eh_range
*range
;
66 register struct eh_range
*child
;
68 for (; child
!= NULL
; child
= child
->next_sibling
)
70 if (pc
< child
->start_pc
)
72 if (pc
<= child
->end_pc
)
73 return find_handler_in_range (pc
, child
, child
->first_child
);
76 cache_range_start
= pc
;
77 cache_next_child
= child
;
78 cache_range_end
= child
== NULL
? range
->end_pc
: child
->start_pc
;
82 /* Find the inner-most handler that contains PC. */
89 if (pc
>= cache_range_start
)
92 if (pc
< cache_range_end
)
94 while (pc
>= h
->end_pc
)
96 cache_next_child
= h
->next_sibling
;
103 cache_next_child
= h
->first_child
;
105 return find_handler_in_range (pc
, h
, cache_next_child
);
114 /* Recursive helper routine for add_handler. */
117 link_handler (start_pc
, end_pc
, handler
, type
, outer
)
118 int start_pc
, end_pc
;
121 struct eh_range
*outer
;
123 struct eh_range
**ptr
;
124 if (start_pc
< outer
->start_pc
|| end_pc
> outer
->end_pc
)
125 return 0; /* invalid or non-nested exception range */
126 if (start_pc
== outer
->start_pc
&& end_pc
== outer
->end_pc
)
128 outer
->handlers
= tree_cons (type
, handler
, outer
->handlers
);
131 ptr
= &outer
->first_child
;
132 for (;; ptr
= &(*ptr
)->next_sibling
)
134 if (*ptr
== NULL
|| end_pc
<= (*ptr
)->start_pc
)
136 struct eh_range
*h
= (struct eh_range
*)
137 oballoc (sizeof (struct eh_range
));
138 h
->start_pc
= start_pc
;
140 h
->next_sibling
= *ptr
;
141 h
->first_child
= NULL
;
143 h
->handlers
= build_tree_list (type
, handler
);
147 else if (start_pc
< (*ptr
)->end_pc
)
148 return link_handler (start_pc
, end_pc
, handler
, type
, *ptr
);
149 /* end_pc > (*ptr)->start_pc && start_pc >= (*ptr)->end_pc. */
153 /* Called to re-initialize the exception machinery for a new method. */
156 method_init_exceptions ()
158 whole_range
.start_pc
= 0;
159 whole_range
.end_pc
= DECL_CODE_LENGTH (current_function_decl
) + 1;
160 whole_range
.outer
= NULL
;
161 whole_range
.first_child
= NULL
;
162 whole_range
.next_sibling
= NULL
;
163 cache_range_start
= 0xFFFFFF;
164 java_set_exception_lang_code ();
168 java_set_exception_lang_code ()
170 set_exception_lang_code (EH_LANG_Java
);
171 set_exception_version_code (1);
175 add_handler (start_pc
, end_pc
, handler
, type
)
176 int start_pc
, end_pc
;
180 return link_handler (start_pc
, end_pc
, handler
, type
, &whole_range
);
184 /* if there are any handlers for this range, issue start of region */
186 expand_start_java_handler (range
)
187 struct eh_range
*range
;
189 expand_eh_region_start ();
193 prepare_eh_table_type (type
)
198 /* The "type" (metch_info) in a (Java) exception table is one:
199 * a) NULL - meaning match any type in a try-finally.
200 * b) a pointer to a (ccmpiled) class (low-order bit 0).
201 * c) a pointer to the Utf8Const name of the class, plus one
202 * (which yields a value with low-order bit 1). */
204 push_obstacks (&permanent_obstack
, &permanent_obstack
);
205 if (type
== NULL_TREE
)
206 exp
= null_pointer_node
;
207 else if (is_compiled_class (type
))
208 exp
= build_class_ref (type
);
211 (PLUS_EXPR
, ptr_type_node
,
212 build_utf8_ref (build_internal_class_name (type
)),
218 /* if there are any handlers for this range, isssue end of range,
219 and then all handler blocks */
221 expand_end_java_handler (range
)
222 struct eh_range
*range
;
224 tree handler
= range
->handlers
;
225 expand_start_all_catch ();
226 for ( ; handler
!= NULL_TREE
; handler
= TREE_CHAIN (handler
))
228 start_catch_handler (prepare_eh_table_type (TREE_PURPOSE (handler
)));
229 /* Push the thrown object on the top of the stack */
230 expand_goto (TREE_VALUE (handler
));
232 expand_end_all_catch ();
235 /* Recursive helper routine for maybe_start_handlers. */
238 check_start_handlers (range
, pc
)
239 struct eh_range
*range
;
242 if (range
!= NULL_EH_RANGE
&& range
->start_pc
== pc
)
244 check_start_handlers (range
->outer
, pc
);
245 expand_start_java_handler (range
);
249 struct eh_range
*current_range
;
251 /* Emit any start-of-try-range start at PC. */
260 current_range
= find_handler (pc
);
261 check_start_handlers (current_range
, pc
);
264 /* Emit any end-of-try-range end at PC. */
273 while (current_range
!= NULL_EH_RANGE
&& current_range
->end_pc
<= pc
)
275 expand_end_java_handler (current_range
);
276 current_range
= current_range
->outer
;
280 /* Emit the handler labels and their code */
287 rtx funcend
= gen_label_rtx ();
290 emit_insns (catch_clauses
);
291 expand_leftover_cleanups ();
293 emit_label (funcend
);