00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026 #include "system.h"
00027 #include "tree.h"
00028 #include "real.h"
00029 #include "rtl.h"
00030 #include "java-tree.h"
00031 #include "javaop.h"
00032 #include "java-opcodes.h"
00033 #include "jcf.h"
00034 #include "function.h"
00035 #include "except.h"
00036 #include "java-except.h"
00037 #include "toplev.h"
00038
00039 static void expand_start_java_handler PARAMS ((struct eh_range *));
00040 static void expand_end_java_handler PARAMS ((struct eh_range *));
00041 static struct eh_range *find_handler_in_range PARAMS ((int, struct eh_range *,
00042 struct eh_range *));
00043 static void link_handler PARAMS ((struct eh_range *, struct eh_range *));
00044 static void check_start_handlers PARAMS ((struct eh_range *, int));
00045 static void free_eh_ranges PARAMS ((struct eh_range *range));
00046
00047 extern struct obstack permanent_obstack;
00048
00049 struct eh_range *current_method_handlers;
00050
00051 struct eh_range *current_try_block = NULL;
00052
00053 struct eh_range *eh_range_freelist = NULL;
00054
00055
00056
00057 static int cache_range_start, cache_range_end;
00058 static struct eh_range *cache_range;
00059 static struct eh_range *cache_next_child;
00060
00061
00062
00063 struct eh_range whole_range;
00064
00065 #if defined(DEBUG_JAVA_BINDING_LEVELS)
00066 int binding_depth;
00067 int is_class_level;
00068 int current_pc;
00069 extern void indent ();
00070
00071 #endif
00072
00073
00074
00075
00076
00077
00078 static struct eh_range *
00079 find_handler_in_range (pc, range, child)
00080 int pc;
00081 struct eh_range *range;
00082 register struct eh_range *child;
00083 {
00084 for (; child != NULL; child = child->next_sibling)
00085 {
00086 if (pc < child->start_pc)
00087 break;
00088 if (pc < child->end_pc)
00089 return find_handler_in_range (pc, child, child->first_child);
00090 }
00091 cache_range = range;
00092 cache_range_start = pc;
00093 cache_next_child = child;
00094 cache_range_end = child == NULL ? range->end_pc : child->start_pc;
00095 return range;
00096 }
00097
00098
00099
00100 struct eh_range *
00101 find_handler (pc)
00102 int pc;
00103 {
00104 struct eh_range *h;
00105 if (pc >= cache_range_start)
00106 {
00107 h = cache_range;
00108 if (pc < cache_range_end)
00109 return h;
00110 while (pc >= h->end_pc)
00111 {
00112 cache_next_child = h->next_sibling;
00113 h = h->outer;
00114 }
00115 }
00116 else
00117 {
00118 h = &whole_range;
00119 cache_next_child = h->first_child;
00120 }
00121 return find_handler_in_range (pc, h, cache_next_child);
00122 }
00123
00124
00125
00126 static void
00127 link_handler (range, outer)
00128 struct eh_range *range, *outer;
00129 {
00130 struct eh_range **ptr;
00131
00132 if (range->start_pc == outer->start_pc && range->end_pc == outer->end_pc)
00133 {
00134 outer->handlers = chainon (outer->handlers, range->handlers);
00135 return;
00136 }
00137
00138
00139
00140 if (range->start_pc <= outer->start_pc && range->end_pc >= outer->end_pc)
00141 {
00142 range->outer = outer->outer;
00143 range->next_sibling = NULL;
00144 range->first_child = outer;
00145 {
00146 struct eh_range **pr = &(outer->outer->first_child);
00147 while (*pr != outer)
00148 pr = &(*pr)->next_sibling;
00149 *pr = range;
00150 }
00151 outer->outer = range;
00152 return;
00153 }
00154
00155
00156 if (range->start_pc < outer->start_pc || range->end_pc > outer->end_pc)
00157 {
00158 struct eh_range *h
00159 = (struct eh_range *) xmalloc (sizeof (struct eh_range));
00160 if (range->start_pc < outer->start_pc)
00161 {
00162 h->start_pc = range->start_pc;
00163 h->end_pc = outer->start_pc;
00164 range->start_pc = outer->start_pc;
00165 }
00166 else
00167 {
00168 h->start_pc = outer->end_pc;
00169 h->end_pc = range->end_pc;
00170 range->end_pc = outer->end_pc;
00171 }
00172 h->first_child = NULL;
00173 h->outer = NULL;
00174 h->handlers = build_tree_list (TREE_PURPOSE (range->handlers),
00175 TREE_VALUE (range->handlers));
00176 h->next_sibling = NULL;
00177
00178
00179 link_handler (h, &whole_range);
00180 link_handler (range, &whole_range);
00181 return;
00182 }
00183
00184 ptr = &outer->first_child;
00185 for (;; ptr = &(*ptr)->next_sibling)
00186 {
00187 if (*ptr == NULL || range->end_pc <= (*ptr)->start_pc)
00188 {
00189 range->next_sibling = *ptr;
00190 range->first_child = NULL;
00191 range->outer = outer;
00192 *ptr = range;
00193 return;
00194 }
00195 else if (range->start_pc < (*ptr)->end_pc)
00196 {
00197 link_handler (range, *ptr);
00198 return;
00199 }
00200
00201 }
00202 }
00203
00204
00205
00206
00207
00208
00209 void
00210 handle_nested_ranges ()
00211 {
00212 struct eh_range *ptr, *next;
00213
00214 ptr = whole_range.first_child;
00215 whole_range.first_child = NULL;
00216 for (; ptr; ptr = next)
00217 {
00218 next = ptr->next_sibling;
00219 ptr->next_sibling = NULL;
00220 link_handler (ptr, &whole_range);
00221 }
00222 }
00223
00224
00225
00226 static void
00227 free_eh_ranges (range)
00228 struct eh_range *range;
00229 {
00230 while (range)
00231 {
00232 struct eh_range *next = range->next_sibling;
00233 free_eh_ranges (range->first_child);
00234 if (range != &whole_range)
00235 free (range);
00236 range = next;
00237 }
00238 }
00239
00240
00241
00242 void
00243 method_init_exceptions ()
00244 {
00245 free_eh_ranges (&whole_range);
00246 whole_range.start_pc = 0;
00247 whole_range.end_pc = DECL_CODE_LENGTH (current_function_decl) + 1;
00248 whole_range.outer = NULL;
00249 whole_range.first_child = NULL;
00250 whole_range.next_sibling = NULL;
00251 cache_range_start = 0xFFFFFF;
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 void
00269 add_handler (start_pc, end_pc, handler, type)
00270 int start_pc, end_pc;
00271 tree handler;
00272 tree type;
00273 {
00274 struct eh_range *ptr, *prev = NULL, *h;
00275
00276 for (ptr = whole_range.first_child; ptr; ptr = ptr->next_sibling)
00277 {
00278 if (start_pc >= ptr->start_pc
00279 && start_pc <= ptr->end_pc
00280 && TREE_PURPOSE (ptr->handlers) == type
00281 && TREE_VALUE (ptr->handlers) == handler)
00282 {
00283
00284 ptr->end_pc = MAX (ptr->end_pc, end_pc);
00285 return;
00286 }
00287 prev = ptr;
00288 }
00289
00290 h = (struct eh_range *) xmalloc (sizeof (struct eh_range));
00291 h->start_pc = start_pc;
00292 h->end_pc = end_pc;
00293 h->first_child = NULL;
00294 h->outer = NULL;
00295 h->handlers = build_tree_list (type, handler);
00296 h->next_sibling = NULL;
00297 h->expanded = 0;
00298
00299 if (prev == NULL)
00300 whole_range.first_child = h;
00301 else
00302 prev->next_sibling = h;
00303 }
00304
00305
00306
00307 static void
00308 expand_start_java_handler (range)
00309 struct eh_range *range;
00310 {
00311 #if defined(DEBUG_JAVA_BINDING_LEVELS)
00312 indent ();
00313 fprintf (stderr, "expand start handler pc %d --> %d\n",
00314 current_pc, range->end_pc);
00315 #endif
00316 range->expanded = 1;
00317 expand_eh_region_start ();
00318 }
00319
00320 tree
00321 prepare_eh_table_type (type)
00322 tree type;
00323 {
00324 tree exp;
00325
00326
00327
00328
00329
00330
00331
00332 if (type == NULL_TREE)
00333 exp = NULL_TREE;
00334 else if (is_compiled_class (type))
00335 exp = build_class_ref (type);
00336 else
00337 exp = fold (build
00338 (PLUS_EXPR, ptr_type_node,
00339 build_utf8_ref (build_internal_class_name (type)),
00340 size_one_node));
00341 return exp;
00342 }
00343
00344
00345
00346
00347
00348 tree
00349 build_exception_object_ref (type)
00350 tree type;
00351 {
00352 tree obj;
00353
00354
00355
00356 obj = build (EXC_PTR_EXPR, build_pointer_type (type));
00357 obj = build (MINUS_EXPR, TREE_TYPE (obj), obj,
00358 TYPE_SIZE_UNIT (TREE_TYPE (obj)));
00359 obj = build1 (INDIRECT_REF, type, obj);
00360
00361 return obj;
00362 }
00363
00364
00365
00366 static void
00367 expand_end_java_handler (range)
00368 struct eh_range *range;
00369 {
00370 tree handler = range->handlers;
00371 force_poplevels (range->start_pc);
00372 expand_start_all_catch ();
00373 for ( ; handler != NULL_TREE; handler = TREE_CHAIN (handler))
00374 {
00375
00376
00377
00378
00379
00380
00381 tree type = TREE_PURPOSE (handler);
00382 if (type == NULL)
00383 type = throwable_type_node;
00384
00385 expand_start_catch (type);
00386 expand_goto (TREE_VALUE (handler));
00387 expand_end_catch ();
00388 }
00389 expand_end_all_catch ();
00390 #if defined(DEBUG_JAVA_BINDING_LEVELS)
00391 indent ();
00392 fprintf (stderr, "expand end handler pc %d <-- %d\n",
00393 current_pc, range->start_pc);
00394 #endif
00395 }
00396
00397
00398
00399 static void
00400 check_start_handlers (range, pc)
00401 struct eh_range *range;
00402 int pc;
00403 {
00404 if (range != NULL_EH_RANGE && range->start_pc == pc)
00405 {
00406 check_start_handlers (range->outer, pc);
00407 if (!range->expanded)
00408 expand_start_java_handler (range);
00409 }
00410 }
00411
00412
00413 static struct eh_range *current_range;
00414
00415
00416
00417
00418 void
00419 maybe_start_try (start_pc, end_pc)
00420 int start_pc;
00421 int end_pc;
00422 {
00423 struct eh_range *range;
00424 if (! doing_eh (1))
00425 return;
00426
00427 range = find_handler (start_pc);
00428 while (range != NULL_EH_RANGE && range->start_pc == start_pc
00429 && range->end_pc < end_pc)
00430 range = range->outer;
00431
00432 current_range = range;
00433 check_start_handlers (range, start_pc);
00434 }
00435
00436
00437
00438
00439 void
00440 maybe_end_try (start_pc, end_pc)
00441 int start_pc;
00442 int end_pc;
00443 {
00444 if (! doing_eh (1))
00445 return;
00446
00447 while (current_range != NULL_EH_RANGE && current_range->end_pc <= end_pc
00448 && current_range->start_pc >= start_pc)
00449 {
00450 expand_end_java_handler (current_range);
00451 current_range = current_range->outer;
00452 }
00453 }