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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #include "config.h"
00055 #include "system.h"
00056 #include "rtl.h"
00057 #include "tree.h"
00058 #include "flags.h"
00059 #include "function.h"
00060 #include "expr.h"
00061 #include "libfuncs.h"
00062 #include "insn-config.h"
00063 #include "except.h"
00064 #include "integrate.h"
00065 #include "hard-reg-set.h"
00066 #include "basic-block.h"
00067 #include "output.h"
00068 #include "dwarf2asm.h"
00069 #include "dwarf2out.h"
00070 #include "dwarf2.h"
00071 #include "toplev.h"
00072 #include "hashtab.h"
00073 #include "intl.h"
00074 #include "ggc.h"
00075 #include "tm_p.h"
00076 #include "target.h"
00077 #include "langhooks.h"
00078
00079
00080
00081 #ifndef EH_RETURN_DATA_REGNO
00082 #define EH_RETURN_DATA_REGNO(N) INVALID_REGNUM
00083 #endif
00084
00085
00086
00087 int flag_non_call_exceptions;
00088
00089
00090
00091 tree (*lang_protect_cleanup_actions) PARAMS ((void));
00092
00093
00094 int (*lang_eh_type_covers) PARAMS ((tree a, tree b));
00095
00096
00097 tree (*lang_eh_runtime_type) PARAMS ((tree));
00098
00099
00100
00101 struct ehl_map_entry GTY(())
00102 {
00103 rtx label;
00104 struct eh_region *region;
00105 };
00106
00107 static int call_site_base;
00108 static GTY ((param_is (union tree_node)))
00109 htab_t type_to_runtime_map;
00110
00111
00112 static GTY(()) tree sjlj_fc_type_node;
00113 static int sjlj_fc_call_site_ofs;
00114 static int sjlj_fc_data_ofs;
00115 static int sjlj_fc_personality_ofs;
00116 static int sjlj_fc_lsda_ofs;
00117 static int sjlj_fc_jbuf_ofs;
00118
00119
00120 struct eh_region GTY(())
00121 {
00122
00123 struct eh_region *outer;
00124
00125
00126 struct eh_region *inner;
00127 struct eh_region *next_peer;
00128
00129
00130 int region_number;
00131
00132
00133
00134 bitmap aka;
00135
00136
00137 enum eh_region_type
00138 {
00139 ERT_UNKNOWN = 0,
00140 ERT_CLEANUP,
00141 ERT_TRY,
00142 ERT_CATCH,
00143 ERT_ALLOWED_EXCEPTIONS,
00144 ERT_MUST_NOT_THROW,
00145 ERT_THROW,
00146 ERT_FIXUP
00147 } type;
00148
00149
00150 union eh_region_u {
00151
00152
00153 struct eh_region_u_try {
00154 struct eh_region *catch;
00155 struct eh_region *last_catch;
00156 struct eh_region *prev_try;
00157 rtx continue_label;
00158 } GTY ((tag ("ERT_TRY"))) try;
00159
00160
00161
00162 struct eh_region_u_catch {
00163 struct eh_region *next_catch;
00164 struct eh_region *prev_catch;
00165 tree type_list;
00166 tree filter_list;
00167 } GTY ((tag ("ERT_CATCH"))) catch;
00168
00169
00170 struct eh_region_u_allowed {
00171 tree type_list;
00172 int filter;
00173 } GTY ((tag ("ERT_ALLOWED_EXCEPTIONS"))) allowed;
00174
00175
00176
00177 struct eh_region_u_throw {
00178 tree type;
00179 } GTY ((tag ("ERT_THROW"))) throw;
00180
00181
00182
00183 struct eh_region_u_cleanup {
00184 tree exp;
00185 struct eh_region *prev_try;
00186 } GTY ((tag ("ERT_CLEANUP"))) cleanup;
00187
00188
00189
00190 struct eh_region_u_fixup {
00191 tree cleanup_exp;
00192 struct eh_region *real_region;
00193 } GTY ((tag ("ERT_FIXUP"))) fixup;
00194 } GTY ((desc ("%0.type"))) u;
00195
00196
00197 rtx label;
00198
00199
00200 rtx landing_pad;
00201
00202
00203 rtx post_landing_pad;
00204
00205
00206
00207 rtx resume;
00208
00209
00210 unsigned may_contain_throw : 1;
00211 };
00212
00213 struct call_site_record GTY(())
00214 {
00215 rtx landing_pad;
00216 int action;
00217 };
00218
00219
00220 struct eh_status GTY(())
00221 {
00222
00223 struct eh_region *region_tree;
00224
00225
00226 struct eh_region ** GTY ((length ("%h.last_region_number"))) region_array;
00227
00228
00229 struct eh_region *cur_region;
00230
00231
00232 struct eh_region *try_region;
00233
00234 rtx filter;
00235 rtx exc_ptr;
00236
00237 int built_landing_pads;
00238 int last_region_number;
00239
00240 varray_type ttype_data;
00241 varray_type ehspec_data;
00242 varray_type action_record_data;
00243
00244 htab_t GTY ((param_is (struct ehl_map_entry))) exception_handler_label_map;
00245
00246 struct call_site_record * GTY ((length ("%h.call_site_data_used")))
00247 call_site_data;
00248 int call_site_data_used;
00249 int call_site_data_size;
00250
00251 rtx ehr_stackadj;
00252 rtx ehr_handler;
00253 rtx ehr_label;
00254
00255 rtx sjlj_fc;
00256 rtx sjlj_exit_after;
00257 };
00258
00259
00260 static int t2r_eq PARAMS ((const PTR,
00261 const PTR));
00262 static hashval_t t2r_hash PARAMS ((const PTR));
00263 static void add_type_for_runtime PARAMS ((tree));
00264 static tree lookup_type_for_runtime PARAMS ((tree));
00265
00266 static struct eh_region *expand_eh_region_end PARAMS ((void));
00267
00268 static rtx get_exception_filter PARAMS ((struct function *));
00269
00270 static void collect_eh_region_array PARAMS ((void));
00271 static void resolve_fixup_regions PARAMS ((void));
00272 static void remove_fixup_regions PARAMS ((void));
00273 static void remove_unreachable_regions PARAMS ((rtx));
00274 static void convert_from_eh_region_ranges_1 PARAMS ((rtx *, int *, int));
00275
00276 static struct eh_region *duplicate_eh_region_1 PARAMS ((struct eh_region *,
00277 struct inline_remap *));
00278 static void duplicate_eh_region_2 PARAMS ((struct eh_region *,
00279 struct eh_region **));
00280 static int ttypes_filter_eq PARAMS ((const PTR,
00281 const PTR));
00282 static hashval_t ttypes_filter_hash PARAMS ((const PTR));
00283 static int ehspec_filter_eq PARAMS ((const PTR,
00284 const PTR));
00285 static hashval_t ehspec_filter_hash PARAMS ((const PTR));
00286 static int add_ttypes_entry PARAMS ((htab_t, tree));
00287 static int add_ehspec_entry PARAMS ((htab_t, htab_t,
00288 tree));
00289 static void assign_filter_values PARAMS ((void));
00290 static void build_post_landing_pads PARAMS ((void));
00291 static void connect_post_landing_pads PARAMS ((void));
00292 static void dw2_build_landing_pads PARAMS ((void));
00293
00294 struct sjlj_lp_info;
00295 static bool sjlj_find_directly_reachable_regions
00296 PARAMS ((struct sjlj_lp_info *));
00297 static void sjlj_assign_call_site_values
00298 PARAMS ((rtx, struct sjlj_lp_info *));
00299 static void sjlj_mark_call_sites
00300 PARAMS ((struct sjlj_lp_info *));
00301 static void sjlj_emit_function_enter PARAMS ((rtx));
00302 static void sjlj_emit_function_exit PARAMS ((void));
00303 static void sjlj_emit_dispatch_table
00304 PARAMS ((rtx, struct sjlj_lp_info *));
00305 static void sjlj_build_landing_pads PARAMS ((void));
00306
00307 static hashval_t ehl_hash PARAMS ((const PTR));
00308 static int ehl_eq PARAMS ((const PTR,
00309 const PTR));
00310 static void add_ehl_entry PARAMS ((rtx,
00311 struct eh_region *));
00312 static void remove_exception_handler_label PARAMS ((rtx));
00313 static void remove_eh_handler PARAMS ((struct eh_region *));
00314 static int for_each_eh_label_1 PARAMS ((PTR *, PTR));
00315
00316 struct reachable_info;
00317
00318
00319 enum reachable_code
00320 {
00321
00322 RNL_NOT_CAUGHT,
00323
00324 RNL_MAYBE_CAUGHT,
00325
00326 RNL_CAUGHT,
00327
00328 RNL_BLOCKED
00329 };
00330
00331 static int check_handled PARAMS ((tree, tree));
00332 static void add_reachable_handler
00333 PARAMS ((struct reachable_info *, struct eh_region *,
00334 struct eh_region *));
00335 static enum reachable_code reachable_next_level
00336 PARAMS ((struct eh_region *, tree, struct reachable_info *));
00337
00338 static int action_record_eq PARAMS ((const PTR,
00339 const PTR));
00340 static hashval_t action_record_hash PARAMS ((const PTR));
00341 static int add_action_record PARAMS ((htab_t, int, int));
00342 static int collect_one_action_chain PARAMS ((htab_t,
00343 struct eh_region *));
00344 static int add_call_site PARAMS ((rtx, int));
00345
00346 static void push_uleb128 PARAMS ((varray_type *,
00347 unsigned int));
00348 static void push_sleb128 PARAMS ((varray_type *, int));
00349 #ifndef HAVE_AS_LEB128
00350 static int dw2_size_of_call_site_table PARAMS ((void));
00351 static int sjlj_size_of_call_site_table PARAMS ((void));
00352 #endif
00353 static void dw2_output_call_site_table PARAMS ((void));
00354 static void sjlj_output_call_site_table PARAMS ((void));
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 int
00365 doing_eh (do_warn)
00366 int do_warn;
00367 {
00368 if (! flag_exceptions)
00369 {
00370 static int warned = 0;
00371 if (! warned && do_warn)
00372 {
00373 error ("exception handling disabled, use -fexceptions to enable");
00374 warned = 1;
00375 }
00376 return 0;
00377 }
00378 return 1;
00379 }
00380
00381
00382 void
00383 init_eh ()
00384 {
00385 if (! flag_exceptions)
00386 return;
00387
00388 type_to_runtime_map = htab_create_ggc (31, t2r_hash, t2r_eq, NULL);
00389
00390
00391
00392 if (USING_SJLJ_EXCEPTIONS)
00393 {
00394 tree f_jbuf, f_per, f_lsda, f_prev, f_cs, f_data, tmp;
00395
00396 sjlj_fc_type_node = (*lang_hooks.types.make_type) (RECORD_TYPE);
00397
00398 f_prev = build_decl (FIELD_DECL, get_identifier ("__prev"),
00399 build_pointer_type (sjlj_fc_type_node));
00400 DECL_FIELD_CONTEXT (f_prev) = sjlj_fc_type_node;
00401
00402 f_cs = build_decl (FIELD_DECL, get_identifier ("__call_site"),
00403 integer_type_node);
00404 DECL_FIELD_CONTEXT (f_cs) = sjlj_fc_type_node;
00405
00406 tmp = build_index_type (build_int_2 (4 - 1, 0));
00407 tmp = build_array_type ((*lang_hooks.types.type_for_mode) (word_mode, 1),
00408 tmp);
00409 f_data = build_decl (FIELD_DECL, get_identifier ("__data"), tmp);
00410 DECL_FIELD_CONTEXT (f_data) = sjlj_fc_type_node;
00411
00412 f_per = build_decl (FIELD_DECL, get_identifier ("__personality"),
00413 ptr_type_node);
00414 DECL_FIELD_CONTEXT (f_per) = sjlj_fc_type_node;
00415
00416 f_lsda = build_decl (FIELD_DECL, get_identifier ("__lsda"),
00417 ptr_type_node);
00418 DECL_FIELD_CONTEXT (f_lsda) = sjlj_fc_type_node;
00419
00420 #ifdef DONT_USE_BUILTIN_SETJMP
00421 #ifdef JMP_BUF_SIZE
00422 tmp = build_int_2 (JMP_BUF_SIZE - 1, 0);
00423 #else
00424
00425
00426
00427
00428 tmp = build_int_2 (FIRST_PSEUDO_REGISTER + 2 - 1, 0);
00429 #endif
00430 #else
00431
00432
00433 tmp = build_int_2 ((GET_MODE_SIZE (STACK_SAVEAREA_MODE (SAVE_NONLOCAL))
00434 / GET_MODE_SIZE (Pmode)) + 2 - 1, 0);
00435 #endif
00436 tmp = build_index_type (tmp);
00437 tmp = build_array_type (ptr_type_node, tmp);
00438 f_jbuf = build_decl (FIELD_DECL, get_identifier ("__jbuf"), tmp);
00439 #ifdef DONT_USE_BUILTIN_SETJMP
00440
00441
00442 DECL_ALIGN (f_jbuf) = BIGGEST_ALIGNMENT;
00443 DECL_USER_ALIGN (f_jbuf) = 1;
00444 #endif
00445 DECL_FIELD_CONTEXT (f_jbuf) = sjlj_fc_type_node;
00446
00447 TYPE_FIELDS (sjlj_fc_type_node) = f_prev;
00448 TREE_CHAIN (f_prev) = f_cs;
00449 TREE_CHAIN (f_cs) = f_data;
00450 TREE_CHAIN (f_data) = f_per;
00451 TREE_CHAIN (f_per) = f_lsda;
00452 TREE_CHAIN (f_lsda) = f_jbuf;
00453
00454 layout_type (sjlj_fc_type_node);
00455
00456
00457
00458 sjlj_fc_call_site_ofs
00459 = (tree_low_cst (DECL_FIELD_OFFSET (f_cs), 1)
00460 + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_cs), 1) / BITS_PER_UNIT);
00461 sjlj_fc_data_ofs
00462 = (tree_low_cst (DECL_FIELD_OFFSET (f_data), 1)
00463 + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_data), 1) / BITS_PER_UNIT);
00464 sjlj_fc_personality_ofs
00465 = (tree_low_cst (DECL_FIELD_OFFSET (f_per), 1)
00466 + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_per), 1) / BITS_PER_UNIT);
00467 sjlj_fc_lsda_ofs
00468 = (tree_low_cst (DECL_FIELD_OFFSET (f_lsda), 1)
00469 + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_lsda), 1) / BITS_PER_UNIT);
00470 sjlj_fc_jbuf_ofs
00471 = (tree_low_cst (DECL_FIELD_OFFSET (f_jbuf), 1)
00472 + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_jbuf), 1) / BITS_PER_UNIT);
00473 }
00474 }
00475
00476 void
00477 init_eh_for_function ()
00478 {
00479 cfun->eh = (struct eh_status *)
00480 ggc_alloc_cleared (sizeof (struct eh_status));
00481 }
00482
00483
00484
00485
00486
00487 void
00488 expand_eh_region_start ()
00489 {
00490 struct eh_region *new_region;
00491 struct eh_region *cur_region;
00492 rtx note;
00493
00494 if (! doing_eh (0))
00495 return;
00496
00497
00498 new_region = (struct eh_region *) ggc_alloc_cleared (sizeof (*new_region));
00499 cur_region = cfun->eh->cur_region;
00500 new_region->outer = cur_region;
00501 if (cur_region)
00502 {
00503 new_region->next_peer = cur_region->inner;
00504 cur_region->inner = new_region;
00505 }
00506 else
00507 {
00508 new_region->next_peer = cfun->eh->region_tree;
00509 cfun->eh->region_tree = new_region;
00510 }
00511 cfun->eh->cur_region = new_region;
00512
00513
00514 new_region->region_number = ++cfun->eh->last_region_number;
00515 note = emit_note (NULL, NOTE_INSN_EH_REGION_BEG);
00516 NOTE_EH_HANDLER (note) = new_region->region_number;
00517 }
00518
00519
00520
00521 static struct eh_region *
00522 expand_eh_region_end ()
00523 {
00524 struct eh_region *cur_region = cfun->eh->cur_region;
00525 rtx note;
00526
00527
00528 note = emit_note (NULL, NOTE_INSN_EH_REGION_END);
00529 NOTE_EH_HANDLER (note) = cur_region->region_number;
00530
00531
00532 cfun->eh->cur_region = cur_region->outer;
00533
00534 return cur_region;
00535 }
00536
00537
00538
00539
00540 void
00541 expand_eh_region_end_cleanup (handler)
00542 tree handler;
00543 {
00544 struct eh_region *region;
00545 tree protect_cleanup_actions;
00546 rtx around_label;
00547 rtx data_save[2];
00548
00549 if (! doing_eh (0))
00550 return;
00551
00552 region = expand_eh_region_end ();
00553 region->type = ERT_CLEANUP;
00554 region->label = gen_label_rtx ();
00555 region->u.cleanup.exp = handler;
00556 region->u.cleanup.prev_try = cfun->eh->try_region;
00557
00558 around_label = gen_label_rtx ();
00559 emit_jump (around_label);
00560
00561 emit_label (region->label);
00562
00563 if (flag_non_call_exceptions || region->may_contain_throw)
00564 {
00565
00566
00567 protect_cleanup_actions
00568 = (lang_protect_cleanup_actions
00569 ? (*lang_protect_cleanup_actions) ()
00570 : NULL_TREE);
00571
00572 if (protect_cleanup_actions)
00573 expand_eh_region_start ();
00574
00575
00576
00577 data_save[0] = gen_reg_rtx (ptr_mode);
00578 emit_move_insn (data_save[0], get_exception_pointer (cfun));
00579 data_save[1] = gen_reg_rtx (word_mode);
00580 emit_move_insn (data_save[1], get_exception_filter (cfun));
00581
00582 expand_expr (handler, const0_rtx, VOIDmode, 0);
00583
00584 emit_move_insn (cfun->eh->exc_ptr, data_save[0]);
00585 emit_move_insn (cfun->eh->filter, data_save[1]);
00586
00587 if (protect_cleanup_actions)
00588 expand_eh_region_end_must_not_throw (protect_cleanup_actions);
00589
00590
00591 do_pending_stack_adjust ();
00592 }
00593
00594
00595
00596
00597 region->resume
00598 = emit_jump_insn (gen_rtx_RESX (VOIDmode, region->region_number));
00599 emit_barrier ();
00600
00601 emit_label (around_label);
00602 }
00603
00604
00605
00606
00607 void
00608 expand_start_all_catch ()
00609 {
00610 struct eh_region *region;
00611
00612 if (! doing_eh (1))
00613 return;
00614
00615 region = expand_eh_region_end ();
00616 region->type = ERT_TRY;
00617 region->u.try.prev_try = cfun->eh->try_region;
00618 region->u.try.continue_label = gen_label_rtx ();
00619
00620 cfun->eh->try_region = region;
00621
00622 emit_jump (region->u.try.continue_label);
00623 }
00624
00625
00626
00627
00628
00629
00630 void
00631 expand_start_catch (type_or_list)
00632 tree type_or_list;
00633 {
00634 struct eh_region *t, *c, *l;
00635 tree type_list;
00636
00637 if (! doing_eh (0))
00638 return;
00639
00640 type_list = type_or_list;
00641
00642 if (type_or_list)
00643 {
00644
00645
00646
00647 tree type_node;
00648
00649 if (TREE_CODE (type_or_list) != TREE_LIST)
00650 type_list = tree_cons (NULL_TREE, type_or_list, NULL_TREE);
00651
00652 type_node = type_list;
00653 for (; type_node; type_node = TREE_CHAIN (type_node))
00654 add_type_for_runtime (TREE_VALUE (type_node));
00655 }
00656
00657 expand_eh_region_start ();
00658
00659 t = cfun->eh->try_region;
00660 c = cfun->eh->cur_region;
00661 c->type = ERT_CATCH;
00662 c->u.catch.type_list = type_list;
00663 c->label = gen_label_rtx ();
00664
00665 l = t->u.try.last_catch;
00666 c->u.catch.prev_catch = l;
00667 if (l)
00668 l->u.catch.next_catch = c;
00669 else
00670 t->u.try.catch = c;
00671 t->u.try.last_catch = c;
00672
00673 emit_label (c->label);
00674 }
00675
00676
00677
00678 void
00679 expand_end_catch ()
00680 {
00681 struct eh_region *try_region, *catch_region;
00682
00683 if (! doing_eh (0))
00684 return;
00685
00686 catch_region = expand_eh_region_end ();
00687 try_region = cfun->eh->try_region;
00688
00689 emit_jump (try_region->u.try.continue_label);
00690 }
00691
00692
00693
00694 void
00695 expand_end_all_catch ()
00696 {
00697 struct eh_region *try_region;
00698
00699 if (! doing_eh (0))
00700 return;
00701
00702 try_region = cfun->eh->try_region;
00703 cfun->eh->try_region = try_region->u.try.prev_try;
00704
00705 emit_label (try_region->u.try.continue_label);
00706 }
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716 void
00717 expand_eh_region_end_allowed (allowed, failure)
00718 tree allowed, failure;
00719 {
00720 struct eh_region *region;
00721 rtx around_label;
00722
00723 if (! doing_eh (0))
00724 return;
00725
00726 region = expand_eh_region_end ();
00727 region->type = ERT_ALLOWED_EXCEPTIONS;
00728 region->u.allowed.type_list = allowed;
00729 region->label = gen_label_rtx ();
00730
00731 for (; allowed ; allowed = TREE_CHAIN (allowed))
00732 add_type_for_runtime (TREE_VALUE (allowed));
00733
00734
00735
00736
00737
00738 around_label = gen_label_rtx ();
00739 emit_jump (around_label);
00740
00741 emit_label (region->label);
00742 expand_expr (failure, const0_rtx, VOIDmode, EXPAND_NORMAL);
00743
00744
00745
00746 do_pending_stack_adjust ();
00747
00748 emit_label (around_label);
00749 }
00750
00751
00752
00753
00754 rtx
00755 expand_builtin_extend_pointer (tree addr_tree)
00756 {
00757 rtx addr = expand_expr (addr_tree, NULL_RTX, ptr_mode, 0);
00758 int extend;
00759
00760 #ifdef POINTERS_EXTEND_UNSIGNED
00761 extend = POINTERS_EXTEND_UNSIGNED;
00762 #else
00763
00764
00765 extend = 1;
00766 #endif
00767
00768 return convert_modes (word_mode, ptr_mode, addr, extend);
00769 }
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779 void
00780 expand_eh_region_end_must_not_throw (failure)
00781 tree failure;
00782 {
00783 struct eh_region *region;
00784 rtx around_label;
00785
00786 if (! doing_eh (0))
00787 return;
00788
00789 region = expand_eh_region_end ();
00790 region->type = ERT_MUST_NOT_THROW;
00791 region->label = gen_label_rtx ();
00792
00793
00794
00795
00796
00797 around_label = gen_label_rtx ();
00798 emit_jump (around_label);
00799
00800 emit_label (region->label);
00801 expand_expr (failure, const0_rtx, VOIDmode, EXPAND_NORMAL);
00802
00803 emit_label (around_label);
00804 }
00805
00806
00807
00808
00809
00810 void
00811 expand_eh_region_end_throw (type)
00812 tree type;
00813 {
00814 struct eh_region *region;
00815
00816 if (! doing_eh (0))
00817 return;
00818
00819 region = expand_eh_region_end ();
00820 region->type = ERT_THROW;
00821 region->u.throw.type = type;
00822 }
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 void
00835 expand_eh_region_end_fixup (handler)
00836 tree handler;
00837 {
00838 struct eh_region *fixup;
00839
00840 if (! doing_eh (0))
00841 return;
00842
00843 fixup = expand_eh_region_end ();
00844 fixup->type = ERT_FIXUP;
00845 fixup->u.fixup.cleanup_exp = handler;
00846 }
00847
00848
00849
00850
00851 void
00852 note_eh_region_may_contain_throw ()
00853 {
00854 struct eh_region *region;
00855
00856 region = cfun->eh->cur_region;
00857 while (region && !region->may_contain_throw)
00858 {
00859 region->may_contain_throw = 1;
00860 region = region->outer;
00861 }
00862 }
00863
00864
00865
00866
00867 rtx
00868 get_exception_pointer (fun)
00869 struct function *fun;
00870 {
00871 rtx exc_ptr = fun->eh->exc_ptr;
00872 if (fun == cfun && ! exc_ptr)
00873 {
00874 exc_ptr = gen_reg_rtx (ptr_mode);
00875 fun->eh->exc_ptr = exc_ptr;
00876 }
00877 return exc_ptr;
00878 }
00879
00880
00881
00882
00883 static rtx
00884 get_exception_filter (fun)
00885 struct function *fun;
00886 {
00887 rtx filter = fun->eh->filter;
00888 if (fun == cfun && ! filter)
00889 {
00890 filter = gen_reg_rtx (word_mode);
00891 fun->eh->filter = filter;
00892 }
00893 return filter;
00894 }
00895
00896
00897
00898
00899
00900
00901
00902 static void
00903 collect_eh_region_array ()
00904 {
00905 struct eh_region **array, *i;
00906
00907 i = cfun->eh->region_tree;
00908 if (! i)
00909 return;
00910
00911 array = ggc_alloc_cleared ((cfun->eh->last_region_number + 1)
00912 * sizeof (*array));
00913 cfun->eh->region_array = array;
00914
00915 while (1)
00916 {
00917 array[i->region_number] = i;
00918
00919
00920 if (i->inner)
00921 i = i->inner;
00922
00923 else if (i->next_peer)
00924 i = i->next_peer;
00925
00926 else
00927 {
00928 do {
00929 i = i->outer;
00930 if (i == NULL)
00931 return;
00932 } while (i->next_peer == NULL);
00933 i = i->next_peer;
00934 }
00935 }
00936 }
00937
00938 static void
00939 resolve_fixup_regions ()
00940 {
00941 int i, j, n = cfun->eh->last_region_number;
00942
00943 for (i = 1; i <= n; ++i)
00944 {
00945 struct eh_region *fixup = cfun->eh->region_array[i];
00946 struct eh_region *cleanup = 0;
00947
00948 if (! fixup || fixup->type != ERT_FIXUP)
00949 continue;
00950
00951 for (j = 1; j <= n; ++j)
00952 {
00953 cleanup = cfun->eh->region_array[j];
00954 if (cleanup->type == ERT_CLEANUP
00955 && cleanup->u.cleanup.exp == fixup->u.fixup.cleanup_exp)
00956 break;
00957 }
00958 if (j > n)
00959 abort ();
00960
00961 fixup->u.fixup.real_region = cleanup->outer;
00962 }
00963 }
00964
00965
00966
00967
00968 static void
00969 remove_fixup_regions ()
00970 {
00971 int i;
00972 rtx insn, note;
00973 struct eh_region *fixup;
00974
00975
00976
00977
00978
00979 for (insn = get_insns(); insn ; insn = NEXT_INSN (insn))
00980 if (INSN_P (insn)
00981 && (note = find_reg_note (insn, REG_EH_REGION, NULL))
00982 && INTVAL (XEXP (note, 0)) > 0
00983 && (fixup = cfun->eh->region_array[INTVAL (XEXP (note, 0))])
00984 && fixup->type == ERT_FIXUP)
00985 {
00986 if (fixup->u.fixup.real_region)
00987 XEXP (note, 0) = GEN_INT (fixup->u.fixup.real_region->region_number);
00988 else
00989 remove_note (insn, note);
00990 }
00991
00992
00993 for (i = cfun->eh->last_region_number; i > 0; --i)
00994 {
00995 fixup = cfun->eh->region_array[i];
00996 if (! fixup)
00997 continue;
00998
00999
01000 if (fixup->type == ERT_CLEANUP)
01001 fixup->u.cleanup.exp = NULL_TREE;
01002
01003 if (fixup->type != ERT_FIXUP)
01004 continue;
01005
01006 if (fixup->inner)
01007 {
01008 struct eh_region *parent, *p, **pp;
01009
01010 parent = fixup->u.fixup.real_region;
01011
01012
01013
01014 for (p = fixup->inner; ; p = p->next_peer)
01015 {
01016 p->outer = parent;
01017 if (! p->next_peer)
01018 break;
01019 }
01020
01021
01022
01023 if (parent)
01024 pp = &parent->inner;
01025 else
01026 pp = &cfun->eh->region_tree;
01027 p->next_peer = *pp;
01028 *pp = fixup->inner;
01029 fixup->inner = NULL;
01030 }
01031
01032 remove_eh_handler (fixup);
01033 }
01034 }
01035
01036
01037
01038 static void
01039 remove_unreachable_regions (insns)
01040 rtx insns;
01041 {
01042 int i, *uid_region_num;
01043 bool *reachable;
01044 struct eh_region *r;
01045 rtx insn;
01046
01047 uid_region_num = xcalloc (get_max_uid (), sizeof(int));
01048 reachable = xcalloc (cfun->eh->last_region_number + 1, sizeof(bool));
01049
01050 for (i = cfun->eh->last_region_number; i > 0; --i)
01051 {
01052 r = cfun->eh->region_array[i];
01053 if (!r || r->region_number != i)
01054 continue;
01055
01056 if (r->resume)
01057 {
01058 if (uid_region_num[INSN_UID (r->resume)])
01059 abort ();
01060 uid_region_num[INSN_UID (r->resume)] = i;
01061 }
01062 if (r->label)
01063 {
01064 if (uid_region_num[INSN_UID (r->label)])
01065 abort ();
01066 uid_region_num[INSN_UID (r->label)] = i;
01067 }
01068 if (r->type == ERT_TRY && r->u.try.continue_label)
01069 {
01070 if (uid_region_num[INSN_UID (r->u.try.continue_label)])
01071 abort ();
01072 uid_region_num[INSN_UID (r->u.try.continue_label)] = i;
01073 }
01074 }
01075
01076 for (insn = insns; insn; insn = NEXT_INSN (insn))
01077 reachable[uid_region_num[INSN_UID (insn)]] = true;
01078
01079 for (i = cfun->eh->last_region_number; i > 0; --i)
01080 {
01081 r = cfun->eh->region_array[i];
01082 if (r && r->region_number == i && !reachable[i])
01083 {
01084
01085
01086 if (r->type == ERT_THROW
01087 && r->outer
01088 && reachable[r->outer->region_number])
01089 continue;
01090
01091 remove_eh_handler (r);
01092 }
01093 }
01094
01095 free (reachable);
01096 free (uid_region_num);
01097 }
01098
01099
01100
01101
01102 static void
01103 convert_from_eh_region_ranges_1 (pinsns, orig_sp, cur)
01104 rtx *pinsns;
01105 int *orig_sp;
01106 int cur;
01107 {
01108 int *sp = orig_sp;
01109 rtx insn, next;
01110
01111 for (insn = *pinsns; insn ; insn = next)
01112 {
01113 next = NEXT_INSN (insn);
01114 if (GET_CODE (insn) == NOTE)
01115 {
01116 int kind = NOTE_LINE_NUMBER (insn);
01117 if (kind == NOTE_INSN_EH_REGION_BEG
01118 || kind == NOTE_INSN_EH_REGION_END)
01119 {
01120 if (kind == NOTE_INSN_EH_REGION_BEG)
01121 {
01122 struct eh_region *r;
01123
01124 *sp++ = cur;
01125 cur = NOTE_EH_HANDLER (insn);
01126
01127 r = cfun->eh->region_array[cur];
01128 if (r->type == ERT_FIXUP)
01129 {
01130 r = r->u.fixup.real_region;
01131 cur = r ? r->region_number : 0;
01132 }
01133 else if (r->type == ERT_CATCH)
01134 {
01135 r = r->outer;
01136 cur = r ? r->region_number : 0;
01137 }
01138 }
01139 else
01140 cur = *--sp;
01141
01142
01143
01144 if (insn == *pinsns)
01145 *pinsns = next;
01146 remove_insn (insn);
01147 continue;
01148 }
01149 }
01150 else if (INSN_P (insn))
01151 {
01152 if (cur > 0
01153 && ! find_reg_note (insn, REG_EH_REGION, NULL_RTX)
01154
01155
01156
01157 && (GET_CODE (insn) == CALL_INSN
01158
01159
01160 || (flag_non_call_exceptions
01161 && GET_CODE (PATTERN (insn)) != CLOBBER
01162 && GET_CODE (PATTERN (insn)) != USE
01163 && may_trap_p (PATTERN (insn)))))
01164 {
01165 REG_NOTES (insn) = alloc_EXPR_LIST (REG_EH_REGION, GEN_INT (cur),
01166 REG_NOTES (insn));
01167 }
01168
01169 if (GET_CODE (insn) == CALL_INSN
01170 && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
01171 {
01172 convert_from_eh_region_ranges_1 (&XEXP (PATTERN (insn), 0),
01173 sp, cur);
01174 convert_from_eh_region_ranges_1 (&XEXP (PATTERN (insn), 1),
01175 sp, cur);
01176 convert_from_eh_region_ranges_1 (&XEXP (PATTERN (insn), 2),
01177 sp, cur);
01178 }
01179 }
01180 }
01181
01182 if (sp != orig_sp)
01183 abort ();
01184 }
01185
01186 void
01187 convert_from_eh_region_ranges ()
01188 {
01189 int *stack;
01190 rtx insns;
01191
01192 collect_eh_region_array ();
01193 resolve_fixup_regions ();
01194
01195 stack = xmalloc (sizeof (int) * (cfun->eh->last_region_number + 1));
01196 insns = get_insns ();
01197 convert_from_eh_region_ranges_1 (&insns, stack, 0);
01198 free (stack);
01199
01200 remove_fixup_regions ();
01201 remove_unreachable_regions (insns);
01202 }
01203
01204 static void
01205 add_ehl_entry (label, region)
01206 rtx label;
01207 struct eh_region *region;
01208 {
01209 struct ehl_map_entry **slot, *entry;
01210
01211 LABEL_PRESERVE_P (label) = 1;
01212
01213 entry = (struct ehl_map_entry *) ggc_alloc (sizeof (*entry));
01214 entry->label = label;
01215 entry->region = region;
01216
01217 slot = (struct ehl_map_entry **)
01218 htab_find_slot (cfun->eh->exception_handler_label_map, entry, INSERT);
01219
01220
01221
01222
01223
01224 if (*slot && !cfun->eh->built_landing_pads)
01225 abort ();
01226
01227 *slot = entry;
01228 }
01229
01230 void
01231 find_exception_handler_labels ()
01232 {
01233 int i;
01234
01235 if (cfun->eh->exception_handler_label_map)
01236 htab_empty (cfun->eh->exception_handler_label_map);
01237 else
01238 {
01239
01240
01241 cfun->eh->exception_handler_label_map
01242 = htab_create_ggc (cfun->eh->last_region_number * 3 / 2,
01243 ehl_hash, ehl_eq, NULL);
01244 }
01245
01246 if (cfun->eh->region_tree == NULL)
01247 return;
01248
01249 for (i = cfun->eh->last_region_number; i > 0; --i)
01250 {
01251 struct eh_region *region = cfun->eh->region_array[i];
01252 rtx lab;
01253
01254 if (! region || region->region_number != i)
01255 continue;
01256 if (cfun->eh->built_landing_pads)
01257 lab = region->landing_pad;
01258 else
01259 lab = region->label;
01260
01261 if (lab)
01262 add_ehl_entry (lab, region);
01263 }
01264
01265
01266
01267 if (USING_SJLJ_EXCEPTIONS && ! cfun->eh->built_landing_pads)
01268 add_ehl_entry (return_label, NULL);
01269 }
01270
01271 bool
01272 current_function_has_exception_handlers ()
01273 {
01274 int i;
01275
01276 for (i = cfun->eh->last_region_number; i > 0; --i)
01277 {
01278 struct eh_region *region = cfun->eh->region_array[i];
01279
01280 if (! region || region->region_number != i)
01281 continue;
01282 if (region->type != ERT_THROW)
01283 return true;
01284 }
01285
01286 return false;
01287 }
01288
01289 static struct eh_region *
01290 duplicate_eh_region_1 (o, map)
01291 struct eh_region *o;
01292 struct inline_remap *map;
01293 {
01294 struct eh_region *n
01295 = (struct eh_region *) ggc_alloc_cleared (sizeof (struct eh_region));
01296
01297 n->region_number = o->region_number + cfun->eh->last_region_number;
01298 n->type = o->type;
01299
01300 switch (n->type)
01301 {
01302 case ERT_CLEANUP:
01303 case ERT_MUST_NOT_THROW:
01304 break;
01305
01306 case ERT_TRY:
01307 if (o->u.try.continue_label)
01308 n->u.try.continue_label
01309 = get_label_from_map (map,
01310 CODE_LABEL_NUMBER (o->u.try.continue_label));
01311 break;
01312
01313 case ERT_CATCH:
01314 n->u.catch.type_list = o->u.catch.type_list;
01315 break;
01316
01317 case ERT_ALLOWED_EXCEPTIONS:
01318 n->u.allowed.type_list = o->u.allowed.type_list;
01319 break;
01320
01321 case ERT_THROW:
01322 n->u.throw.type = o->u.throw.type;
01323
01324 default:
01325 abort ();
01326 }
01327
01328 if (o->label)
01329 n->label = get_label_from_map (map, CODE_LABEL_NUMBER (o->label));
01330 if (o->resume)
01331 {
01332 n->resume = map->insn_map[INSN_UID (o->resume)];
01333 if (n->resume == NULL)
01334 abort ();
01335 }
01336
01337 return n;
01338 }
01339
01340 static void
01341 duplicate_eh_region_2 (o, n_array)
01342 struct eh_region *o;
01343 struct eh_region **n_array;
01344 {
01345 struct eh_region *n = n_array[o->region_number];
01346
01347 switch (n->type)
01348 {
01349 case ERT_TRY:
01350 n->u.try.catch = n_array[o->u.try.catch->region_number];
01351 n->u.try.last_catch = n_array[o->u.try.last_catch->region_number];
01352 break;
01353
01354 case ERT_CATCH:
01355 if (o->u.catch.next_catch)
01356 n->u.catch.next_catch = n_array[o->u.catch.next_catch->region_number];
01357 if (o->u.catch.prev_catch)
01358 n->u.catch.prev_catch = n_array[o->u.catch.prev_catch->region_number];
01359 break;
01360
01361 default:
01362 break;
01363 }
01364
01365 if (o->outer)
01366 n->outer = n_array[o->outer->region_number];
01367 if (o->inner)
01368 n->inner = n_array[o->inner->region_number];
01369 if (o->next_peer)
01370 n->next_peer = n_array[o->next_peer->region_number];
01371 }
01372
01373 int
01374 duplicate_eh_regions (ifun, map)
01375 struct function *ifun;
01376 struct inline_remap *map;
01377 {
01378 int ifun_last_region_number = ifun->eh->last_region_number;
01379 struct eh_region **n_array, *root, *cur;
01380 int i;
01381
01382 if (ifun_last_region_number == 0)
01383 return 0;
01384
01385 n_array = xcalloc (ifun_last_region_number + 1, sizeof (*n_array));
01386
01387 for (i = 1; i <= ifun_last_region_number; ++i)
01388 {
01389 cur = ifun->eh->region_array[i];
01390 if (!cur || cur->region_number != i)
01391 continue;
01392 n_array[i] = duplicate_eh_region_1 (cur, map);
01393 }
01394 for (i = 1; i <= ifun_last_region_number; ++i)
01395 {
01396 cur = ifun->eh->region_array[i];
01397 if (!cur || cur->region_number != i)
01398 continue;
01399 duplicate_eh_region_2 (cur, n_array);
01400 }
01401
01402 root = n_array[ifun->eh->region_tree->region_number];
01403 cur = cfun->eh->cur_region;
01404 if (cur)
01405 {
01406 struct eh_region *p = cur->inner;
01407 if (p)
01408 {
01409 while (p->next_peer)
01410 p = p->next_peer;
01411 p->next_peer = root;
01412 }
01413 else
01414 cur->inner = root;
01415
01416 for (i = 1; i <= ifun_last_region_number; ++i)
01417 if (n_array[i] && n_array[i]->outer == NULL)
01418 n_array[i]->outer = cur;
01419 }
01420 else
01421 {
01422 struct eh_region *p = cfun->eh->region_tree;
01423 if (p)
01424 {
01425 while (p->next_peer)
01426 p = p->next_peer;
01427 p->next_peer = root;
01428 }
01429 else
01430 cfun->eh->region_tree = root;
01431 }
01432
01433 free (n_array);
01434
01435 i = cfun->eh->last_region_number;
01436 cfun->eh->last_region_number = i + ifun_last_region_number;
01437 return i;
01438 }
01439
01440
01441 static int
01442 t2r_eq (pentry, pdata)
01443 const PTR pentry;
01444 const PTR pdata;
01445 {
01446 tree entry = (tree) pentry;
01447 tree data = (tree) pdata;
01448
01449 return TREE_PURPOSE (entry) == data;
01450 }
01451
01452 static hashval_t
01453 t2r_hash (pentry)
01454 const PTR pentry;
01455 {
01456 tree entry = (tree) pentry;
01457 return TYPE_HASH (TREE_PURPOSE (entry));
01458 }
01459
01460 static void
01461 add_type_for_runtime (type)
01462 tree type;
01463 {
01464 tree *slot;
01465
01466 slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type,
01467 TYPE_HASH (type), INSERT);
01468 if (*slot == NULL)
01469 {
01470 tree runtime = (*lang_eh_runtime_type) (type);
01471 *slot = tree_cons (type, runtime, NULL_TREE);
01472 }
01473 }
01474
01475 static tree
01476 lookup_type_for_runtime (type)
01477 tree type;
01478 {
01479 tree *slot;
01480
01481 slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type,
01482 TYPE_HASH (type), NO_INSERT);
01483
01484
01485 return TREE_VALUE (*slot);
01486 }
01487
01488
01489
01490
01491 struct ttypes_filter GTY(())
01492 {
01493 tree t;
01494 int filter;
01495 };
01496
01497
01498
01499
01500 static int
01501 ttypes_filter_eq (pentry, pdata)
01502 const PTR pentry;
01503 const PTR pdata;
01504 {
01505 const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
01506 tree data = (tree) pdata;
01507
01508 return entry->t == data;
01509 }
01510
01511 static hashval_t
01512 ttypes_filter_hash (pentry)
01513 const PTR pentry;
01514 {
01515 const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
01516 return TYPE_HASH (entry->t);
01517 }
01518
01519
01520
01521
01522
01523
01524 static int
01525 ehspec_filter_eq (pentry, pdata)
01526 const PTR pentry;
01527 const PTR pdata;
01528 {
01529 const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
01530 const struct ttypes_filter *data = (const struct ttypes_filter *) pdata;
01531
01532 return type_list_equal (entry->t, data->t);
01533 }
01534
01535
01536
01537 static hashval_t
01538 ehspec_filter_hash (pentry)
01539 const PTR pentry;
01540 {
01541 const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
01542 hashval_t h = 0;
01543 tree list;
01544
01545 for (list = entry->t; list ; list = TREE_CHAIN (list))
01546 h = (h << 5) + (h >> 27) + TYPE_HASH (TREE_VALUE (list));
01547 return h;
01548 }
01549
01550
01551
01552
01553 static int
01554 add_ttypes_entry (ttypes_hash, type)
01555 htab_t ttypes_hash;
01556 tree type;
01557 {
01558 struct ttypes_filter **slot, *n;
01559
01560 slot = (struct ttypes_filter **)
01561 htab_find_slot_with_hash (ttypes_hash, type, TYPE_HASH (type), INSERT);
01562
01563 if ((n = *slot) == NULL)
01564 {
01565
01566
01567 n = (struct ttypes_filter *) xmalloc (sizeof (*n));
01568 n->t = type;
01569 n->filter = VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data) + 1;
01570 *slot = n;
01571
01572 VARRAY_PUSH_TREE (cfun->eh->ttype_data, type);
01573 }
01574
01575 return n->filter;
01576 }
01577
01578
01579
01580
01581 static int
01582 add_ehspec_entry (ehspec_hash, ttypes_hash, list)
01583 htab_t ehspec_hash;
01584 htab_t ttypes_hash;
01585 tree list;
01586 {
01587 struct ttypes_filter **slot, *n;
01588 struct ttypes_filter dummy;
01589
01590 dummy.t = list;
01591 slot = (struct ttypes_filter **)
01592 htab_find_slot (ehspec_hash, &dummy, INSERT);
01593
01594 if ((n = *slot) == NULL)
01595 {
01596
01597
01598 n = (struct ttypes_filter *) xmalloc (sizeof (*n));
01599 n->t = list;
01600 n->filter = -(VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data) + 1);
01601 *slot = n;
01602
01603
01604
01605 for (; list ; list = TREE_CHAIN (list))
01606 push_uleb128 (&cfun->eh->ehspec_data,
01607 add_ttypes_entry (ttypes_hash, TREE_VALUE (list)));
01608 VARRAY_PUSH_UCHAR (cfun->eh->ehspec_data, 0);
01609 }
01610
01611 return n->filter;
01612 }
01613
01614
01615
01616
01617
01618
01619 static void
01620 assign_filter_values ()
01621 {
01622 int i;
01623 htab_t ttypes, ehspec;
01624
01625 VARRAY_TREE_INIT (cfun->eh->ttype_data, 16, "ttype_data");
01626 VARRAY_UCHAR_INIT (cfun->eh->ehspec_data, 64, "ehspec_data");
01627
01628 ttypes = htab_create (31, ttypes_filter_hash, ttypes_filter_eq, free);
01629 ehspec = htab_create (31, ehspec_filter_hash, ehspec_filter_eq, free);
01630
01631 for (i = cfun->eh->last_region_number; i > 0; --i)
01632 {
01633 struct eh_region *r = cfun->eh->region_array[i];
01634
01635
01636 if (!r || r->region_number != i)
01637 continue;
01638
01639 switch (r->type)
01640 {
01641 case ERT_CATCH:
01642
01643
01644 r->u.catch.filter_list = NULL_TREE;
01645
01646 if (r->u.catch.type_list != NULL)
01647 {
01648
01649
01650 tree tp_node = r->u.catch.type_list;
01651
01652 for (;tp_node; tp_node = TREE_CHAIN (tp_node))
01653 {
01654 int flt = add_ttypes_entry (ttypes, TREE_VALUE (tp_node));
01655 tree flt_node = build_int_2 (flt, 0);
01656
01657 r->u.catch.filter_list
01658 = tree_cons (NULL_TREE, flt_node, r->u.catch.filter_list);
01659 }
01660 }
01661 else
01662 {
01663
01664
01665 int flt = add_ttypes_entry (ttypes, NULL);
01666 tree flt_node = build_int_2 (flt, 0);
01667
01668 r->u.catch.filter_list
01669 = tree_cons (NULL_TREE, flt_node, r->u.catch.filter_list);
01670 }
01671
01672 break;
01673
01674 case ERT_ALLOWED_EXCEPTIONS:
01675 r->u.allowed.filter
01676 = add_ehspec_entry (ehspec, ttypes, r->u.allowed.type_list);
01677 break;
01678
01679 default:
01680 break;
01681 }
01682 }
01683
01684 htab_delete (ttypes);
01685 htab_delete (ehspec);
01686 }
01687
01688 static void
01689 build_post_landing_pads ()
01690 {
01691 int i;
01692
01693 for (i = cfun->eh->last_region_number; i > 0; --i)
01694 {
01695 struct eh_region *region = cfun->eh->region_array[i];
01696 rtx seq;
01697
01698
01699 if (!region || region->region_number != i)
01700 continue;
01701
01702 switch (region->type)
01703 {
01704 case ERT_TRY:
01705
01706
01707
01708
01709
01710
01711 region->post_landing_pad = gen_label_rtx ();
01712
01713 start_sequence ();
01714
01715 emit_label (region->post_landing_pad);
01716
01717
01718
01719
01720 {
01721 struct eh_region *c;
01722 for (c = region->u.try.catch; c ; c = c->u.catch.next_catch)
01723 {
01724 if (c->u.catch.type_list == NULL)
01725 emit_jump (c->label);
01726 else
01727 {
01728
01729
01730
01731 tree tp_node = c->u.catch.type_list;
01732 tree flt_node = c->u.catch.filter_list;
01733
01734 for (; tp_node; )
01735 {
01736 emit_cmp_and_jump_insns
01737 (cfun->eh->filter,
01738 GEN_INT (tree_low_cst (TREE_VALUE (flt_node), 0)),
01739 EQ, NULL_RTX, word_mode, 0, c->label);
01740
01741 tp_node = TREE_CHAIN (tp_node);
01742 flt_node = TREE_CHAIN (flt_node);
01743 }
01744 }
01745 }
01746 }
01747
01748
01749
01750
01751 region->resume
01752 = emit_jump_insn (gen_rtx_RESX (VOIDmode, region->region_number));
01753 emit_barrier ();
01754
01755 seq = get_insns ();
01756 end_sequence ();
01757
01758 emit_insn_before (seq, region->u.try.catch->label);
01759 break;
01760
01761 case ERT_ALLOWED_EXCEPTIONS:
01762 region->post_landing_pad = gen_label_rtx ();
01763
01764 start_sequence ();
01765
01766 emit_label (region->post_landing_pad);
01767
01768 emit_cmp_and_jump_insns (cfun->eh->filter,
01769 GEN_INT (region->u.allowed.filter),
01770 EQ, NULL_RTX, word_mode, 0, region->label);
01771
01772
01773
01774
01775 region->resume
01776 = emit_jump_insn (gen_rtx_RESX (VOIDmode, region->region_number));
01777 emit_barrier ();
01778
01779 seq = get_insns ();
01780 end_sequence ();
01781
01782 emit_insn_before (seq, region->label);
01783 break;
01784
01785 case ERT_CLEANUP:
01786 case ERT_MUST_NOT_THROW:
01787 region->post_landing_pad = region->label;
01788 break;
01789
01790 case ERT_CATCH:
01791 case ERT_THROW:
01792
01793 break;
01794
01795 default:
01796 abort ();
01797 }
01798 }
01799 }
01800
01801
01802
01803
01804 static void
01805 connect_post_landing_pads ()
01806 {
01807 int i;
01808
01809 for (i = cfun->eh->last_region_number; i > 0; --i)
01810 {
01811 struct eh_region *region = cfun->eh->region_array[i];
01812 struct eh_region *outer;
01813 rtx seq;
01814
01815
01816 if (!region || region->region_number != i)
01817 continue;
01818
01819
01820
01821 if (! region->resume || INSN_DELETED_P (region->resume))
01822 continue;
01823
01824
01825 for (outer = region->outer; outer ; outer = outer->outer)
01826 if (outer->post_landing_pad)
01827 break;
01828
01829 start_sequence ();
01830
01831 if (outer)
01832 emit_jump (outer->post_landing_pad);
01833 else
01834 emit_library_call (unwind_resume_libfunc, LCT_THROW,
01835 VOIDmode, 1, cfun->eh->exc_ptr, ptr_mode);
01836
01837 seq = get_insns ();
01838 end_sequence ();
01839 emit_insn_before (seq, region->resume);
01840 delete_insn (region->resume);
01841 }
01842 }
01843
01844
01845 static void
01846 dw2_build_landing_pads ()
01847 {
01848 int i;
01849 unsigned int j;
01850
01851 for (i = cfun->eh->last_region_number; i > 0; --i)
01852 {
01853 struct eh_region *region = cfun->eh->region_array[i];
01854 rtx seq;
01855 bool clobbers_hard_regs = false;
01856
01857
01858 if (!region || region->region_number != i)
01859 continue;
01860
01861 if (region->type != ERT_CLEANUP
01862 && region->type != ERT_TRY
01863 && region->type != ERT_ALLOWED_EXCEPTIONS)
01864 continue;
01865
01866 start_sequence ();
01867
01868 region->landing_pad = gen_label_rtx ();
01869 emit_label (region->landing_pad);
01870
01871 #ifdef HAVE_exception_receiver
01872 if (HAVE_exception_receiver)
01873 emit_insn (gen_exception_receiver ());
01874 else
01875 #endif
01876 #ifdef HAVE_nonlocal_goto_receiver
01877 if (HAVE_nonlocal_goto_receiver)
01878 emit_insn (gen_nonlocal_goto_receiver ());
01879 else
01880 #endif
01881 { }
01882
01883
01884
01885
01886 for (j = 0; ; ++j)
01887 {
01888 unsigned r = EH_RETURN_DATA_REGNO (j);
01889 if (r == INVALID_REGNUM)
01890 break;
01891 if (! call_used_regs[r])
01892 {
01893 emit_insn (gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, r)));
01894 clobbers_hard_regs = true;
01895 }
01896 }
01897
01898 if (clobbers_hard_regs)
01899 {
01900
01901
01902
01903
01904 emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
01905 }
01906
01907 emit_move_insn (cfun->eh->exc_ptr,
01908 gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0)));
01909 emit_move_insn (cfun->eh->filter,
01910 gen_rtx_REG (word_mode, EH_RETURN_DATA_REGNO (1)));
01911
01912 seq = get_insns ();
01913 end_sequence ();
01914
01915 emit_insn_before (seq, region->post_landing_pad);
01916 }
01917 }
01918
01919
01920 struct sjlj_lp_info
01921 {
01922 int directly_reachable;
01923 int action_index;
01924 int dispatch_index;
01925 int call_site_index;
01926 };
01927
01928 static bool
01929 sjlj_find_directly_reachable_regions (lp_info)
01930 struct sjlj_lp_info *lp_info;
01931 {
01932 rtx insn;
01933 bool found_one = false;
01934
01935 for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
01936 {
01937 struct eh_region *region;
01938 enum reachable_code rc;
01939 tree type_thrown;
01940 rtx note;
01941
01942 if (! INSN_P (insn))
01943 continue;
01944
01945 note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
01946 if (!note || INTVAL (XEXP (note, 0)) <= 0)
01947 continue;
01948
01949 region = cfun->eh->region_array[INTVAL (XEXP (note, 0))];
01950
01951 type_thrown = NULL_TREE;
01952 if (region->type == ERT_THROW)
01953 {
01954 type_thrown = region->u.throw.type;
01955 region = region->outer;
01956 }
01957
01958
01959
01960 rc = RNL_NOT_CAUGHT;
01961 for (; region; region = region->outer)
01962 {
01963 rc = reachable_next_level (region, type_thrown, 0);
01964 if (rc != RNL_NOT_CAUGHT)
01965 break;
01966 }
01967 if (rc == RNL_MAYBE_CAUGHT || rc == RNL_CAUGHT)
01968 {
01969 lp_info[region->region_number].directly_reachable = 1;
01970 found_one = true;
01971 }
01972 }
01973
01974 return found_one;
01975 }
01976
01977 static void
01978 sjlj_assign_call_site_values (dispatch_label, lp_info)
01979 rtx dispatch_label;
01980 struct sjlj_lp_info *lp_info;
01981 {
01982 htab_t ar_hash;
01983 int i, index;
01984
01985
01986
01987 VARRAY_UCHAR_INIT (cfun->eh->action_record_data, 64, "action_record_data");
01988 ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
01989
01990 for (i = cfun->eh->last_region_number; i > 0; --i)
01991 if (lp_info[i].directly_reachable)
01992 {
01993 struct eh_region *r = cfun->eh->region_array[i];
01994 r->landing_pad = dispatch_label;
01995 lp_info[i].action_index = collect_one_action_chain (ar_hash, r);
01996 if (lp_info[i].action_index != -1)
01997 cfun->uses_eh_lsda = 1;
01998 }
01999
02000 htab_delete (ar_hash);
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012 index = 0;
02013 for (i = cfun->eh->last_region_number; i > 0; --i)
02014 if (lp_info[i].directly_reachable)
02015 lp_info[i].dispatch_index = index++;
02016
02017
02018
02019
02020
02021 call_site_base = 1;
02022 for (i = cfun->eh->last_region_number; i > 0; --i)
02023 if (lp_info[i].directly_reachable)
02024 {
02025 int action = lp_info[i].action_index;
02026
02027
02028 if (action == -2)
02029 index = 0;
02030
02031 else if (action == -1)
02032 index = -1;
02033
02034 else
02035 index = add_call_site (GEN_INT (lp_info[i].dispatch_index), action);
02036
02037 lp_info[i].call_site_index = index;
02038 }
02039 }
02040
02041 static void
02042 sjlj_mark_call_sites (lp_info)
02043 struct sjlj_lp_info *lp_info;
02044 {
02045 int last_call_site = -2;
02046 rtx insn, mem;
02047
02048 for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
02049 {
02050 struct eh_region *region;
02051 int this_call_site;
02052 rtx note, before, p;
02053
02054
02055 if (GET_CODE (insn) == CODE_LABEL)
02056 last_call_site = -2;
02057
02058 if (! INSN_P (insn))
02059 continue;
02060
02061 note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
02062 if (!note)
02063 {
02064
02065
02066
02067 if (GET_CODE (insn) == CALL_INSN
02068 || (flag_non_call_exceptions
02069 && may_trap_p (PATTERN (insn))))
02070 this_call_site = -1;
02071 else
02072 continue;
02073 }
02074 else
02075 {
02076
02077 if (INTVAL (XEXP (note, 0)) <= 0)
02078 continue;
02079
02080 region = cfun->eh->region_array[INTVAL (XEXP (note, 0))];
02081 this_call_site = lp_info[region->region_number].call_site_index;
02082 }
02083
02084 if (this_call_site == last_call_site)
02085 continue;
02086
02087
02088 before = insn;
02089 if (GET_CODE (insn) == CALL_INSN)
02090 before = find_first_parameter_load (insn, NULL_RTX);
02091
02092 start_sequence ();
02093 mem = adjust_address (cfun->eh->sjlj_fc, TYPE_MODE (integer_type_node),
02094 sjlj_fc_call_site_ofs);
02095 emit_move_insn (mem, GEN_INT (this_call_site));
02096 p = get_insns ();
02097 end_sequence ();
02098
02099 emit_insn_before (p, before);
02100 last_call_site = this_call_site;
02101 }
02102 }
02103
02104
02105
02106 static void
02107 sjlj_emit_function_enter (dispatch_label)
02108 rtx dispatch_label;
02109 {
02110 rtx fn_begin, fc, mem, seq;
02111
02112 fc = cfun->eh->sjlj_fc;
02113
02114 start_sequence ();
02115
02116
02117
02118
02119 assemble_external_libcall (eh_personality_libfunc);
02120 mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
02121 emit_move_insn (mem, eh_personality_libfunc);
02122
02123 mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
02124 if (cfun->uses_eh_lsda)
02125 {
02126 char buf[20];
02127 ASM_GENERATE_INTERNAL_LABEL (buf, "LLSDA", current_function_funcdef_no);
02128 emit_move_insn (mem, gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)));
02129 }
02130 else
02131 emit_move_insn (mem, const0_rtx);
02132
02133 #ifdef DONT_USE_BUILTIN_SETJMP
02134 {
02135 rtx x, note;
02136 x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_RETURNS_TWICE,
02137 TYPE_MODE (integer_type_node), 1,
02138 plus_constant (XEXP (fc, 0),
02139 sjlj_fc_jbuf_ofs), Pmode);
02140
02141 note = emit_note (NULL, NOTE_INSN_EXPECTED_VALUE);
02142 NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, x, const0_rtx);
02143
02144 emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
02145 TYPE_MODE (integer_type_node), 0, dispatch_label);
02146 }
02147 #else
02148 expand_builtin_setjmp_setup (plus_constant (XEXP (fc, 0), sjlj_fc_jbuf_ofs),
02149 dispatch_label);
02150 #endif
02151
02152 emit_library_call (unwind_sjlj_register_libfunc, LCT_NORMAL, VOIDmode,
02153 1, XEXP (fc, 0), Pmode);
02154
02155 seq = get_insns ();
02156 end_sequence ();
02157
02158
02159
02160
02161
02162 for (fn_begin = get_insns (); ; fn_begin = NEXT_INSN (fn_begin))
02163 if (GET_CODE (fn_begin) == NOTE
02164 && NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_FUNCTION_BEG)
02165 break;
02166 emit_insn_after (seq, fn_begin);
02167 }
02168
02169
02170
02171
02172 void
02173 sjlj_emit_function_exit_after (after)
02174 rtx after;
02175 {
02176 cfun->eh->sjlj_exit_after = after;
02177 }
02178
02179 static void
02180 sjlj_emit_function_exit ()
02181 {
02182 rtx seq;
02183
02184 start_sequence ();
02185
02186 emit_library_call (unwind_sjlj_unregister_libfunc, LCT_NORMAL, VOIDmode,
02187 1, XEXP (cfun->eh->sjlj_fc, 0), Pmode);
02188
02189 seq = get_insns ();
02190 end_sequence ();
02191
02192
02193
02194
02195
02196 emit_insn_after (seq, cfun->eh->sjlj_exit_after);
02197 }
02198
02199 static void
02200 sjlj_emit_dispatch_table (dispatch_label, lp_info)
02201 rtx dispatch_label;
02202 struct sjlj_lp_info *lp_info;
02203 {
02204 int i, first_reachable;
02205 rtx mem, dispatch, seq, fc;
02206
02207 fc = cfun->eh->sjlj_fc;
02208
02209 start_sequence ();
02210
02211 emit_label (dispatch_label);
02212
02213 #ifndef DONT_USE_BUILTIN_SETJMP
02214 expand_builtin_setjmp_receiver (dispatch_label);
02215 #endif
02216
02217
02218
02219 mem = adjust_address (fc, TYPE_MODE (integer_type_node),
02220 sjlj_fc_call_site_ofs);
02221 dispatch = copy_to_reg (mem);
02222
02223 mem = adjust_address (fc, word_mode, sjlj_fc_data_ofs);
02224 if (word_mode != Pmode)
02225 {
02226 #ifdef POINTERS_EXTEND_UNSIGNED
02227 mem = convert_memory_address (Pmode, mem);
02228 #else
02229 mem = convert_to_mode (Pmode, mem, 0);
02230 #endif
02231 }
02232 emit_move_insn (cfun->eh->exc_ptr, mem);
02233
02234 mem = adjust_address (fc, word_mode, sjlj_fc_data_ofs + UNITS_PER_WORD);
02235 emit_move_insn (cfun->eh->filter, mem);
02236
02237
02238
02239
02240 first_reachable = 0;
02241 for (i = cfun->eh->last_region_number; i > 0; --i)
02242 {
02243 if (! lp_info[i].directly_reachable)
02244 continue;
02245
02246 if (! first_reachable)
02247 {
02248 first_reachable = i;
02249 continue;
02250 }
02251
02252 emit_cmp_and_jump_insns (dispatch, GEN_INT (lp_info[i].dispatch_index),
02253 EQ, NULL_RTX, TYPE_MODE (integer_type_node), 0,
02254 cfun->eh->region_array[i]->post_landing_pad);
02255 }
02256
02257 seq = get_insns ();
02258 end_sequence ();
02259
02260 emit_insn_before (seq, (cfun->eh->region_array[first_reachable]
02261 ->post_landing_pad));
02262 }
02263
02264 static void
02265 sjlj_build_landing_pads ()
02266 {
02267 struct sjlj_lp_info *lp_info;
02268
02269 lp_info = (struct sjlj_lp_info *) xcalloc (cfun->eh->last_region_number + 1,
02270 sizeof (struct sjlj_lp_info));
02271
02272 if (sjlj_find_directly_reachable_regions (lp_info))
02273 {
02274 rtx dispatch_label = gen_label_rtx ();
02275
02276 cfun->eh->sjlj_fc
02277 = assign_stack_local (TYPE_MODE (sjlj_fc_type_node),
02278 int_size_in_bytes (sjlj_fc_type_node),
02279 TYPE_ALIGN (sjlj_fc_type_node));
02280
02281 sjlj_assign_call_site_values (dispatch_label, lp_info);
02282 sjlj_mark_call_sites (lp_info);
02283
02284 sjlj_emit_function_enter (dispatch_label);
02285 sjlj_emit_dispatch_table (dispatch_label, lp_info);
02286 sjlj_emit_function_exit ();
02287 }
02288
02289 free (lp_info);
02290 }
02291
02292 void
02293 finish_eh_generation ()
02294 {
02295
02296 if (cfun->eh->region_tree == NULL)
02297 return;
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308 cleanup_cfg (CLEANUP_PRE_LOOP | CLEANUP_NO_INSN_DEL);
02309
02310
02311
02312 get_exception_pointer (cfun);
02313 get_exception_filter (cfun);
02314
02315
02316
02317 assign_filter_values ();
02318 build_post_landing_pads ();
02319 connect_post_landing_pads ();
02320 if (USING_SJLJ_EXCEPTIONS)
02321 sjlj_build_landing_pads ();
02322 else
02323 dw2_build_landing_pads ();
02324
02325 cfun->eh->built_landing_pads = 1;
02326
02327
02328 find_exception_handler_labels ();
02329 rebuild_jump_labels (get_insns ());
02330 find_basic_blocks (get_insns (), max_reg_num (), 0);
02331 cleanup_cfg (CLEANUP_PRE_LOOP | CLEANUP_NO_INSN_DEL);
02332 }
02333
02334 static hashval_t
02335 ehl_hash (pentry)
02336 const PTR pentry;
02337 {
02338 struct ehl_map_entry *entry = (struct ehl_map_entry *) pentry;
02339
02340
02341 const hashval_t scaled_golden_ratio = 0x9e3779b9;
02342 return CODE_LABEL_NUMBER (entry->label) * scaled_golden_ratio;
02343 }
02344
02345 static int
02346 ehl_eq (pentry, pdata)
02347 const PTR pentry;
02348 const PTR pdata;
02349 {
02350 struct ehl_map_entry *entry = (struct ehl_map_entry *) pentry;
02351 struct ehl_map_entry *data = (struct ehl_map_entry *) pdata;
02352
02353 return entry->label == data->label;
02354 }
02355
02356
02357
02358
02359
02360 static void
02361 remove_exception_handler_label (label)
02362 rtx label;
02363 {
02364 struct ehl_map_entry **slot, tmp;
02365
02366
02367
02368 if (cfun->eh->exception_handler_label_map == NULL)
02369 return;
02370
02371 tmp.label = label;
02372 slot = (struct ehl_map_entry **)
02373 htab_find_slot (cfun->eh->exception_handler_label_map, &tmp, NO_INSERT);
02374 if (! slot)
02375 abort ();
02376
02377 htab_clear_slot (cfun->eh->exception_handler_label_map, (void **) slot);
02378 }
02379
02380
02381
02382 static void
02383 remove_eh_handler (region)
02384 struct eh_region *region;
02385 {
02386 struct eh_region **pp, **pp_start, *p, *outer, *inner;
02387 rtx lab;
02388
02389
02390
02391
02392
02393
02394
02395 outer = region->outer;
02396 cfun->eh->region_array[region->region_number] = outer;
02397 if (region->aka)
02398 {
02399 int i;
02400 EXECUTE_IF_SET_IN_BITMAP (region->aka, 0, i,
02401 { cfun->eh->region_array[i] = outer; });
02402 }
02403
02404 if (outer)
02405 {
02406 if (!outer->aka)
02407 outer->aka = BITMAP_GGC_ALLOC ();
02408 if (region->aka)
02409 bitmap_a_or_b (outer->aka, outer->aka, region->aka);
02410 bitmap_set_bit (outer->aka, region->region_number);
02411 }
02412
02413 if (cfun->eh->built_landing_pads)
02414 lab = region->landing_pad;
02415 else
02416 lab = region->label;
02417 if (lab)
02418 remove_exception_handler_label (lab);
02419
02420 if (outer)
02421 pp_start = &outer->inner;
02422 else
02423 pp_start = &cfun->eh->region_tree;
02424 for (pp = pp_start, p = *pp; p != region; pp = &p->next_peer, p = *pp)
02425 continue;
02426 *pp = region->next_peer;
02427
02428 inner = region->inner;
02429 if (inner)
02430 {
02431 for (p = inner; p->next_peer ; p = p->next_peer)
02432 p->outer = outer;
02433 p->outer = outer;
02434
02435 p->next_peer = *pp_start;
02436 *pp_start = inner;
02437 }
02438
02439 if (region->type == ERT_CATCH)
02440 {
02441 struct eh_region *try, *next, *prev;
02442
02443 for (try = region->next_peer;
02444 try->type == ERT_CATCH;
02445 try = try->next_peer)
02446 continue;
02447 if (try->type != ERT_TRY)
02448 abort ();
02449
02450 next = region->u.catch.next_catch;
02451 prev = region->u.catch.prev_catch;
02452
02453 if (next)
02454 next->u.catch.prev_catch = prev;
02455 else
02456 try->u.try.last_catch = prev;
02457 if (prev)
02458 prev->u.catch.next_catch = next;
02459 else
02460 {
02461 try->u.try.catch = next;
02462 if (! next)
02463 remove_eh_handler (try);
02464 }
02465 }
02466 }
02467
02468
02469
02470
02471
02472 void
02473 maybe_remove_eh_handler (label)
02474 rtx label;
02475 {
02476 struct ehl_map_entry **slot, tmp;
02477 struct eh_region *region;
02478
02479
02480
02481
02482
02483 if (cfun->eh->built_landing_pads)
02484 return;
02485
02486 tmp.label = label;
02487 slot = (struct ehl_map_entry **)
02488 htab_find_slot (cfun->eh->exception_handler_label_map, &tmp, NO_INSERT);
02489 if (! slot)
02490 return;
02491 region = (*slot)->region;
02492 if (! region)
02493 return;
02494
02495
02496
02497
02498
02499 if (region->type == ERT_MUST_NOT_THROW)
02500 {
02501 htab_clear_slot (cfun->eh->exception_handler_label_map, (void **) slot);
02502 region->label = NULL_RTX;
02503 }
02504 else
02505 remove_eh_handler (region);
02506 }
02507
02508
02509
02510
02511 void
02512 for_each_eh_label (callback)
02513 void (*callback) PARAMS ((rtx));
02514 {
02515 htab_traverse (cfun->eh->exception_handler_label_map, for_each_eh_label_1,
02516 (void *)callback);
02517 }
02518
02519 static int
02520 for_each_eh_label_1 (pentry, data)
02521 PTR *pentry;
02522 PTR data;
02523 {
02524 struct ehl_map_entry *entry = *(struct ehl_map_entry **)pentry;
02525 void (*callback) PARAMS ((rtx)) = (void (*) PARAMS ((rtx))) data;
02526
02527 (*callback) (entry->label);
02528 return 1;
02529 }
02530
02531
02532
02533
02534 struct reachable_info GTY(())
02535 {
02536 tree types_caught;
02537 tree types_allowed;
02538 rtx handlers;
02539 };
02540
02541
02542
02543
02544 static int
02545 check_handled (handled, type)
02546 tree handled, type;
02547 {
02548 tree t;
02549
02550
02551 if (! lang_eh_type_covers)
02552 {
02553 for (t = handled; t ; t = TREE_CHAIN (t))
02554 if (TREE_VALUE (t) == type)
02555 return 1;
02556 }
02557 else
02558 {
02559 for (t = handled; t ; t = TREE_CHAIN (t))
02560 if ((*lang_eh_type_covers) (TREE_VALUE (t), type))
02561 return 1;
02562 }
02563
02564 return 0;
02565 }
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575 static void
02576 add_reachable_handler (info, lp_region, region)
02577 struct reachable_info *info;
02578 struct eh_region *lp_region;
02579 struct eh_region *region;
02580 {
02581 if (! info)
02582 return;
02583
02584 if (cfun->eh->built_landing_pads)
02585 {
02586 if (! info->handlers)
02587 info->handlers = alloc_INSN_LIST (lp_region->landing_pad, NULL_RTX);
02588 }
02589 else
02590 info->handlers = alloc_INSN_LIST (region->label, info->handlers);
02591 }
02592
02593
02594
02595
02596
02597
02598 static enum reachable_code
02599 reachable_next_level (region, type_thrown, info)
02600 struct eh_region *region;
02601 tree type_thrown;
02602 struct reachable_info *info;
02603 {
02604 switch (region->type)
02605 {
02606 case ERT_CLEANUP:
02607
02608
02609
02610 add_reachable_handler (info, region, region);
02611 return RNL_MAYBE_CAUGHT;
02612
02613 case ERT_TRY:
02614 {
02615 struct eh_region *c;
02616 enum reachable_code ret = RNL_NOT_CAUGHT;
02617
02618 for (c = region->u.try.catch; c ; c = c->u.catch.next_catch)
02619 {
02620
02621 if (c->u.catch.type_list == NULL)
02622 {
02623 add_reachable_handler (info, region, c);
02624 return RNL_CAUGHT;
02625 }
02626
02627 if (type_thrown)
02628 {
02629
02630 tree tp_node = c->u.catch.type_list;
02631
02632 for (; tp_node; tp_node = TREE_CHAIN (tp_node))
02633 {
02634 tree type = TREE_VALUE (tp_node);
02635
02636 if (type == type_thrown
02637 || (lang_eh_type_covers
02638 && (*lang_eh_type_covers) (type, type_thrown)))
02639 {
02640 add_reachable_handler (info, region, c);
02641 return RNL_CAUGHT;
02642 }
02643 }
02644
02645
02646
02647 if (lang_eh_type_covers)
02648 return RNL_NOT_CAUGHT;
02649 }
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664 if (! info)
02665 ret = RNL_MAYBE_CAUGHT;
02666 else
02667 {
02668 tree tp_node = c->u.catch.type_list;
02669 bool maybe_reachable = false;
02670
02671
02672
02673 for (; tp_node; tp_node = TREE_CHAIN (tp_node))
02674 {
02675 tree type = TREE_VALUE (tp_node);
02676
02677 if (! check_handled (info->types_caught, type))
02678 {
02679 info->types_caught
02680 = tree_cons (NULL, type, info->types_caught);
02681
02682 maybe_reachable = true;
02683 }
02684 }
02685
02686 if (maybe_reachable)
02687 {
02688 add_reachable_handler (info, region, c);
02689
02690
02691
02692 ret = RNL_MAYBE_CAUGHT;
02693 }
02694 }
02695 }
02696
02697 return ret;
02698 }
02699
02700 case ERT_ALLOWED_EXCEPTIONS:
02701
02702 if (region->u.allowed.type_list == NULL_TREE)
02703 {
02704 add_reachable_handler (info, region, region);
02705 return RNL_CAUGHT;
02706 }
02707
02708
02709
02710 if (info)
02711 info->types_allowed = tree_cons (NULL_TREE,
02712 region->u.allowed.type_list,
02713 info->types_allowed);
02714
02715
02716
02717
02718 if (type_thrown && lang_eh_type_covers)
02719 {
02720 if (check_handled (region->u.allowed.type_list, type_thrown))
02721 return RNL_NOT_CAUGHT;
02722 else
02723 {
02724 add_reachable_handler (info, region, region);
02725 return RNL_CAUGHT;
02726 }
02727 }
02728
02729 add_reachable_handler (info, region, region);
02730 return RNL_MAYBE_CAUGHT;
02731
02732 case ERT_CATCH:
02733
02734 return RNL_NOT_CAUGHT;
02735
02736 case ERT_MUST_NOT_THROW:
02737
02738
02739
02740
02741 if (info && info->handlers)
02742 {
02743 add_reachable_handler (info, region, region);
02744 return RNL_CAUGHT;
02745 }
02746 else
02747 return RNL_BLOCKED;
02748
02749 case ERT_THROW:
02750 case ERT_FIXUP:
02751 case ERT_UNKNOWN:
02752
02753 break;
02754 }
02755
02756 abort ();
02757 }
02758
02759
02760
02761
02762 rtx
02763 reachable_handlers (insn)
02764 rtx insn;
02765 {
02766 struct reachable_info info;
02767 struct eh_region *region;
02768 tree type_thrown;
02769 int region_number;
02770
02771 if (GET_CODE (insn) == JUMP_INSN
02772 && GET_CODE (PATTERN (insn)) == RESX)
02773 region_number = XINT (PATTERN (insn), 0);
02774 else
02775 {
02776 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
02777 if (!note || INTVAL (XEXP (note, 0)) <= 0)
02778 return NULL;
02779 region_number = INTVAL (XEXP (note, 0));
02780 }
02781
02782 memset (&info, 0, sizeof (info));
02783
02784 region = cfun->eh->region_array[region_number];
02785
02786 type_thrown = NULL_TREE;
02787 if (GET_CODE (insn) == JUMP_INSN
02788 && GET_CODE (PATTERN (insn)) == RESX)
02789 {
02790
02791
02792 if (region == NULL)
02793 return NULL;
02794 region = region->outer;
02795 }
02796 else if (region->type == ERT_THROW)
02797 {
02798 type_thrown = region->u.throw.type;
02799 region = region->outer;
02800 }
02801
02802 while (region)
02803 {
02804 if (reachable_next_level (region, type_thrown, &info) >= RNL_CAUGHT)
02805 break;
02806
02807
02808
02809
02810 if (region->type == ERT_CLEANUP)
02811 region = region->u.cleanup.prev_try;
02812 else
02813 region = region->outer;
02814 }
02815
02816 return info.handlers;
02817 }
02818
02819
02820
02821
02822 bool
02823 can_throw_internal (insn)
02824 rtx insn;
02825 {
02826 struct eh_region *region;
02827 tree type_thrown;
02828 rtx note;
02829
02830 if (! INSN_P (insn))
02831 return false;
02832
02833 if (GET_CODE (insn) == INSN
02834 && GET_CODE (PATTERN (insn)) == SEQUENCE)
02835 insn = XVECEXP (PATTERN (insn), 0, 0);
02836
02837 if (GET_CODE (insn) == CALL_INSN
02838 && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
02839 {
02840 int i;
02841 for (i = 0; i < 3; ++i)
02842 {
02843 rtx sub = XEXP (PATTERN (insn), i);
02844 for (; sub ; sub = NEXT_INSN (sub))
02845 if (can_throw_internal (sub))
02846 return true;
02847 }
02848 return false;
02849 }
02850
02851
02852 note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
02853 if (!note || INTVAL (XEXP (note, 0)) <= 0)
02854 return false;
02855
02856 region = cfun->eh->region_array[INTVAL (XEXP (note, 0))];
02857
02858 type_thrown = NULL_TREE;
02859 if (region->type == ERT_THROW)
02860 {
02861 type_thrown = region->u.throw.type;
02862 region = region->outer;
02863 }
02864
02865
02866
02867
02868 for (; region; region = region->outer)
02869 {
02870 enum reachable_code how = reachable_next_level (region, type_thrown, 0);
02871 if (how == RNL_BLOCKED)
02872 return false;
02873 if (how != RNL_NOT_CAUGHT)
02874 return true;
02875 }
02876
02877 return false;
02878 }
02879
02880
02881
02882
02883 bool
02884 can_throw_external (insn)
02885 rtx insn;
02886 {
02887 struct eh_region *region;
02888 tree type_thrown;
02889 rtx note;
02890
02891 if (! INSN_P (insn))
02892 return false;
02893
02894 if (GET_CODE (insn) == INSN
02895 && GET_CODE (PATTERN (insn)) == SEQUENCE)
02896 insn = XVECEXP (PATTERN (insn), 0, 0);
02897
02898 if (GET_CODE (insn) == CALL_INSN
02899 && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
02900 {
02901 int i;
02902 for (i = 0; i < 3; ++i)
02903 {
02904 rtx sub = XEXP (PATTERN (insn), i);
02905 for (; sub ; sub = NEXT_INSN (sub))
02906 if (can_throw_external (sub))
02907 return true;
02908 }
02909 return false;
02910 }
02911
02912 note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
02913 if (!note)
02914 {
02915
02916
02917
02918
02919
02920 return (GET_CODE (insn) == CALL_INSN
02921 || (flag_non_call_exceptions
02922 && may_trap_p (PATTERN (insn))));
02923 }
02924 if (INTVAL (XEXP (note, 0)) <= 0)
02925 return false;
02926
02927 region = cfun->eh->region_array[INTVAL (XEXP (note, 0))];
02928
02929 type_thrown = NULL_TREE;
02930 if (region->type == ERT_THROW)
02931 {
02932 type_thrown = region->u.throw.type;
02933 region = region->outer;
02934 }
02935
02936
02937
02938 for (; region ; region = region->outer)
02939 if (reachable_next_level (region, type_thrown, NULL) >= RNL_CAUGHT)
02940 return false;
02941
02942 return true;
02943 }
02944
02945
02946
02947 void
02948 set_nothrow_function_flags ()
02949 {
02950 rtx insn;
02951
02952 current_function_nothrow = 1;
02953
02954
02955
02956
02957
02958
02959
02960 cfun->all_throwers_are_sibcalls = 1;
02961
02962 if (! flag_exceptions)
02963 return;
02964
02965 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
02966 if (can_throw_external (insn))
02967 {
02968 current_function_nothrow = 0;
02969
02970 if (GET_CODE (insn) != CALL_INSN || !SIBLING_CALL_P (insn))
02971 {
02972 cfun->all_throwers_are_sibcalls = 0;
02973 return;
02974 }
02975 }
02976
02977 for (insn = current_function_epilogue_delay_list; insn;
02978 insn = XEXP (insn, 1))
02979 if (can_throw_external (insn))
02980 {
02981 current_function_nothrow = 0;
02982
02983 if (GET_CODE (insn) != CALL_INSN || !SIBLING_CALL_P (insn))
02984 {
02985 cfun->all_throwers_are_sibcalls = 0;
02986 return;
02987 }
02988 }
02989 }
02990
02991
02992
02993
02994
02995
02996
02997 void
02998 expand_builtin_unwind_init ()
02999 {
03000
03001
03002 current_function_has_nonlocal_label = 1;
03003
03004 #ifdef SETUP_FRAME_ADDRESSES
03005 SETUP_FRAME_ADDRESSES ();
03006 #endif
03007 }
03008
03009 rtx
03010 expand_builtin_eh_return_data_regno (arglist)
03011 tree arglist;
03012 {
03013 tree which = TREE_VALUE (arglist);
03014 unsigned HOST_WIDE_INT iwhich;
03015
03016 if (TREE_CODE (which) != INTEGER_CST)
03017 {
03018 error ("argument of `__builtin_eh_return_regno' must be constant");
03019 return constm1_rtx;
03020 }
03021
03022 iwhich = tree_low_cst (which, 1);
03023 iwhich = EH_RETURN_DATA_REGNO (iwhich);
03024 if (iwhich == INVALID_REGNUM)
03025 return constm1_rtx;
03026
03027 #ifdef DWARF_FRAME_REGNUM
03028 iwhich = DWARF_FRAME_REGNUM (iwhich);
03029 #else
03030 iwhich = DBX_REGISTER_NUMBER (iwhich);
03031 #endif
03032
03033 return GEN_INT (iwhich);
03034 }
03035
03036
03037
03038
03039 rtx
03040 expand_builtin_extract_return_addr (addr_tree)
03041 tree addr_tree;
03042 {
03043 rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, 0);
03044
03045 if (GET_MODE (addr) != Pmode
03046 && GET_MODE (addr) != VOIDmode)
03047 {
03048 #ifdef POINTERS_EXTEND_UNSIGNED
03049 addr = convert_memory_address (Pmode, addr);
03050 #else
03051 addr = convert_to_mode (Pmode, addr, 0);
03052 #endif
03053 }
03054
03055
03056 #ifdef MASK_RETURN_ADDR
03057 expand_and (Pmode, addr, MASK_RETURN_ADDR, addr);
03058 #endif
03059
03060
03061 #if defined (RETURN_ADDR_OFFSET)
03062 addr = plus_constant (addr, RETURN_ADDR_OFFSET);
03063 #endif
03064
03065 return addr;
03066 }
03067
03068
03069
03070
03071
03072 rtx
03073 expand_builtin_frob_return_addr (addr_tree)
03074 tree addr_tree;
03075 {
03076 rtx addr = expand_expr (addr_tree, NULL_RTX, ptr_mode, 0);
03077
03078 #ifdef POINTERS_EXTEND_UNSIGNED
03079 if (GET_MODE (addr) != Pmode)
03080 addr = convert_memory_address (Pmode, addr);
03081 #endif
03082
03083 #ifdef RETURN_ADDR_OFFSET
03084 addr = force_reg (Pmode, addr);
03085 addr = plus_constant (addr, -RETURN_ADDR_OFFSET);
03086 #endif
03087
03088 return addr;
03089 }
03090
03091
03092
03093
03094 void
03095 expand_builtin_eh_return (stackadj_tree, handler_tree)
03096 tree stackadj_tree ATTRIBUTE_UNUSED;
03097 tree handler_tree;
03098 {
03099 rtx tmp;
03100
03101 #ifdef EH_RETURN_STACKADJ_RTX
03102 tmp = expand_expr (stackadj_tree, cfun->eh->ehr_stackadj, VOIDmode, 0);
03103 #ifdef POINTERS_EXTEND_UNSIGNED
03104 if (GET_MODE (tmp) != Pmode)
03105 tmp = convert_memory_address (Pmode, tmp);
03106 #endif
03107 if (!cfun->eh->ehr_stackadj)
03108 cfun->eh->ehr_stackadj = copy_to_reg (tmp);
03109 else if (tmp != cfun->eh->ehr_stackadj)
03110 emit_move_insn (cfun->eh->ehr_stackadj, tmp);
03111 #endif
03112
03113 tmp = expand_expr (handler_tree, cfun->eh->ehr_handler, VOIDmode, 0);
03114 #ifdef POINTERS_EXTEND_UNSIGNED
03115 if (GET_MODE (tmp) != Pmode)
03116 tmp = convert_memory_address (Pmode, tmp);
03117 #endif
03118 if (!cfun->eh->ehr_handler)
03119 cfun->eh->ehr_handler = copy_to_reg (tmp);
03120 else if (tmp != cfun->eh->ehr_handler)
03121 emit_move_insn (cfun->eh->ehr_handler, tmp);
03122
03123 if (!cfun->eh->ehr_label)
03124 cfun->eh->ehr_label = gen_label_rtx ();
03125 emit_jump (cfun->eh->ehr_label);
03126 }
03127
03128 void
03129 expand_eh_return ()
03130 {
03131 rtx around_label;
03132
03133 if (! cfun->eh->ehr_label)
03134 return;
03135
03136 current_function_calls_eh_return = 1;
03137
03138 #ifdef EH_RETURN_STACKADJ_RTX
03139 emit_move_insn (EH_RETURN_STACKADJ_RTX, const0_rtx);
03140 #endif
03141
03142 around_label = gen_label_rtx ();
03143 emit_jump (around_label);
03144
03145 emit_label (cfun->eh->ehr_label);
03146 clobber_return_register ();
03147
03148 #ifdef EH_RETURN_STACKADJ_RTX
03149 emit_move_insn (EH_RETURN_STACKADJ_RTX, cfun->eh->ehr_stackadj);
03150 #endif
03151
03152 #ifdef HAVE_eh_return
03153 if (HAVE_eh_return)
03154 emit_insn (gen_eh_return (cfun->eh->ehr_handler));
03155 else
03156 #endif
03157 {
03158 #ifdef EH_RETURN_HANDLER_RTX
03159 emit_move_insn (EH_RETURN_HANDLER_RTX, cfun->eh->ehr_handler);
03160 #else
03161 error ("__builtin_eh_return not supported on this target");
03162 #endif
03163 }
03164
03165 emit_label (around_label);
03166 }
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179 struct action_record
03180 {
03181 int offset;
03182 int filter;
03183 int next;
03184 };
03185
03186 static int
03187 action_record_eq (pentry, pdata)
03188 const PTR pentry;
03189 const PTR pdata;
03190 {
03191 const struct action_record *entry = (const struct action_record *) pentry;
03192 const struct action_record *data = (const struct action_record *) pdata;
03193 return entry->filter == data->filter && entry->next == data->next;
03194 }
03195
03196 static hashval_t
03197 action_record_hash (pentry)
03198 const PTR pentry;
03199 {
03200 const struct action_record *entry = (const struct action_record *) pentry;
03201 return entry->next * 1009 + entry->filter;
03202 }
03203
03204 static int
03205 add_action_record (ar_hash, filter, next)
03206 htab_t ar_hash;
03207 int filter, next;
03208 {
03209 struct action_record **slot, *new, tmp;
03210
03211 tmp.filter = filter;
03212 tmp.next = next;
03213 slot = (struct action_record **) htab_find_slot (ar_hash, &tmp, INSERT);
03214
03215 if ((new = *slot) == NULL)
03216 {
03217 new = (struct action_record *) xmalloc (sizeof (*new));
03218 new->offset = VARRAY_ACTIVE_SIZE (cfun->eh->action_record_data) + 1;
03219 new->filter = filter;
03220 new->next = next;
03221 *slot = new;
03222
03223
03224
03225
03226
03227
03228 push_sleb128 (&cfun->eh->action_record_data, filter);
03229 if (next)
03230 next -= VARRAY_ACTIVE_SIZE (cfun->eh->action_record_data) + 1;
03231 push_sleb128 (&cfun->eh->action_record_data, next);
03232 }
03233
03234 return new->offset;
03235 }
03236
03237 static int
03238 collect_one_action_chain (ar_hash, region)
03239 htab_t ar_hash;
03240 struct eh_region *region;
03241 {
03242 struct eh_region *c;
03243 int next;
03244
03245
03246
03247 if (region == NULL)
03248 return -1;
03249
03250 switch (region->type)
03251 {
03252 case ERT_CLEANUP:
03253
03254
03255
03256
03257
03258
03259 next = collect_one_action_chain (ar_hash, region->outer);
03260 if (next <= 0)
03261 return 0;
03262 for (c = region->outer; c ; c = c->outer)
03263 if (c->type == ERT_CLEANUP)
03264 return next;
03265 return add_action_record (ar_hash, 0, next);
03266
03267 case ERT_TRY:
03268
03269
03270
03271
03272 next = -3;
03273 for (c = region->u.try.last_catch; c ; c = c->u.catch.prev_catch)
03274 {
03275 if (c->u.catch.type_list == NULL)
03276 {
03277
03278
03279 int filter
03280 = TREE_INT_CST_LOW (TREE_VALUE (c->u.catch.filter_list));
03281
03282 next = add_action_record (ar_hash, filter, 0);
03283 }
03284 else
03285 {
03286
03287
03288 tree flt_node;
03289
03290 if (next == -3)
03291 {
03292 next = collect_one_action_chain (ar_hash, region->outer);
03293
03294
03295 if (next == -1)
03296 next = 0;
03297
03298
03299
03300
03301 else if (next <= 0)
03302 next = add_action_record (ar_hash, 0, 0);
03303 }
03304
03305 flt_node = c->u.catch.filter_list;
03306 for (; flt_node; flt_node = TREE_CHAIN (flt_node))
03307 {
03308 int filter = TREE_INT_CST_LOW (TREE_VALUE (flt_node));
03309 next = add_action_record (ar_hash, filter, next);
03310 }
03311 }
03312 }
03313 return next;
03314
03315 case ERT_ALLOWED_EXCEPTIONS:
03316
03317
03318 next = collect_one_action_chain (ar_hash, region->outer);
03319 return add_action_record (ar_hash, region->u.allowed.filter,
03320 next < 0 ? 0 : next);
03321
03322 case ERT_MUST_NOT_THROW:
03323
03324
03325
03326
03327 return -2;
03328
03329 case ERT_CATCH:
03330 case ERT_THROW:
03331
03332
03333 return collect_one_action_chain (ar_hash, region->outer);
03334
03335 default:
03336 abort ();
03337 }
03338 }
03339
03340 static int
03341 add_call_site (landing_pad, action)
03342 rtx landing_pad;
03343 int action;
03344 {
03345 struct call_site_record *data = cfun->eh->call_site_data;
03346 int used = cfun->eh->call_site_data_used;
03347 int size = cfun->eh->call_site_data_size;
03348
03349 if (used >= size)
03350 {
03351 size = (size ? size * 2 : 64);
03352 data = (struct call_site_record *)
03353 ggc_realloc (data, sizeof (*data) * size);
03354 cfun->eh->call_site_data = data;
03355 cfun->eh->call_site_data_size = size;
03356 }
03357
03358 data[used].landing_pad = landing_pad;
03359 data[used].action = action;
03360
03361 cfun->eh->call_site_data_used = used + 1;
03362
03363 return used + call_site_base;
03364 }
03365
03366
03367
03368
03369
03370 void
03371 convert_to_eh_region_ranges ()
03372 {
03373 rtx insn, iter, note;
03374 htab_t ar_hash;
03375 int last_action = -3;
03376 rtx last_action_insn = NULL_RTX;
03377 rtx last_landing_pad = NULL_RTX;
03378 rtx first_no_action_insn = NULL_RTX;
03379 int call_site = 0;
03380
03381 if (USING_SJLJ_EXCEPTIONS || cfun->eh->region_tree == NULL)
03382 return;
03383
03384 VARRAY_UCHAR_INIT (cfun->eh->action_record_data, 64, "action_record_data");
03385
03386 ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
03387
03388 for (iter = get_insns (); iter ; iter = NEXT_INSN (iter))
03389 if (INSN_P (iter))
03390 {
03391 struct eh_region *region;
03392 int this_action;
03393 rtx this_landing_pad;
03394
03395 insn = iter;
03396 if (GET_CODE (insn) == INSN
03397 && GET_CODE (PATTERN (insn)) == SEQUENCE)
03398 insn = XVECEXP (PATTERN (insn), 0, 0);
03399
03400 note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
03401 if (!note)
03402 {
03403 if (! (GET_CODE (insn) == CALL_INSN
03404 || (flag_non_call_exceptions
03405 && may_trap_p (PATTERN (insn)))))
03406 continue;
03407 this_action = -1;
03408 region = NULL;
03409 }
03410 else
03411 {
03412 if (INTVAL (XEXP (note, 0)) <= 0)
03413 continue;
03414 region = cfun->eh->region_array[INTVAL (XEXP (note, 0))];
03415 this_action = collect_one_action_chain (ar_hash, region);
03416 }
03417
03418
03419
03420 if (this_action != -1)
03421 cfun->uses_eh_lsda = 1;
03422
03423
03424
03425 else if (last_action == -3)
03426 {
03427 first_no_action_insn = iter;
03428 last_action = -1;
03429 }
03430
03431
03432
03433 if (this_action >= 0)
03434 {
03435 struct eh_region *o;
03436 for (o = region; ! o->landing_pad ; o = o->outer)
03437 continue;
03438 this_landing_pad = o->landing_pad;
03439 }
03440 else
03441 this_landing_pad = NULL_RTX;
03442
03443
03444
03445 if (last_action != this_action
03446 || last_landing_pad != this_landing_pad)
03447 {
03448
03449
03450
03451 if (last_action >= -1)
03452 {
03453
03454 if (first_no_action_insn)
03455 {
03456 call_site = add_call_site (NULL_RTX, 0);
03457 note = emit_note_before (NOTE_INSN_EH_REGION_BEG,
03458 first_no_action_insn);
03459 NOTE_EH_HANDLER (note) = call_site;
03460 first_no_action_insn = NULL_RTX;
03461 }
03462
03463 note = emit_note_after (NOTE_INSN_EH_REGION_END,
03464 last_action_insn);
03465 NOTE_EH_HANDLER (note) = call_site;
03466 }
03467
03468
03469
03470 if (this_action >= -1)
03471 {
03472 call_site = add_call_site (this_landing_pad,
03473 this_action < 0 ? 0 : this_action);
03474 note = emit_note_before (NOTE_INSN_EH_REGION_BEG, iter);
03475 NOTE_EH_HANDLER (note) = call_site;
03476 }
03477
03478 last_action = this_action;
03479 last_landing_pad = this_landing_pad;
03480 }
03481 last_action_insn = iter;
03482 }
03483
03484 if (last_action >= -1 && ! first_no_action_insn)
03485 {
03486 note = emit_note_after (NOTE_INSN_EH_REGION_END, last_action_insn);
03487 NOTE_EH_HANDLER (note) = call_site;
03488 }
03489
03490 htab_delete (ar_hash);
03491 }
03492
03493
03494 static void
03495 push_uleb128 (data_area, value)
03496 varray_type *data_area;
03497 unsigned int value;
03498 {
03499 do
03500 {
03501 unsigned char byte = value & 0x7f;
03502 value >>= 7;
03503 if (value)
03504 byte |= 0x80;
03505 VARRAY_PUSH_UCHAR (*data_area, byte);
03506 }
03507 while (value);
03508 }
03509
03510 static void
03511 push_sleb128 (data_area, value)
03512 varray_type *data_area;
03513 int value;
03514 {
03515 unsigned char byte;
03516 int more;
03517
03518 do
03519 {
03520 byte = value & 0x7f;
03521 value >>= 7;
03522 more = ! ((value == 0 && (byte & 0x40) == 0)
03523 || (value == -1 && (byte & 0x40) != 0));
03524 if (more)
03525 byte |= 0x80;
03526 VARRAY_PUSH_UCHAR (*data_area, byte);
03527 }
03528 while (more);
03529 }
03530
03531
03532 #ifndef HAVE_AS_LEB128
03533 static int
03534 dw2_size_of_call_site_table ()
03535 {
03536 int n = cfun->eh->call_site_data_used;
03537 int size = n * (4 + 4 + 4);
03538 int i;
03539
03540 for (i = 0; i < n; ++i)
03541 {
03542 struct call_site_record *cs = &cfun->eh->call_site_data[i];
03543 size += size_of_uleb128 (cs->action);
03544 }
03545
03546 return size;
03547 }
03548
03549 static int
03550 sjlj_size_of_call_site_table ()
03551 {
03552 int n = cfun->eh->call_site_data_used;
03553 int size = 0;
03554 int i;
03555
03556 for (i = 0; i < n; ++i)
03557 {
03558 struct call_site_record *cs = &cfun->eh->call_site_data[i];
03559 size += size_of_uleb128 (INTVAL (cs->landing_pad));
03560 size += size_of_uleb128 (cs->action);
03561 }
03562
03563 return size;
03564 }
03565 #endif
03566
03567 static void
03568 dw2_output_call_site_table ()
03569 {
03570 const char *const function_start_lab
03571 = IDENTIFIER_POINTER (current_function_func_begin_label);
03572 int n = cfun->eh->call_site_data_used;
03573 int i;
03574
03575 for (i = 0; i < n; ++i)
03576 {
03577 struct call_site_record *cs = &cfun->eh->call_site_data[i];
03578 char reg_start_lab[32];
03579 char reg_end_lab[32];
03580 char landing_pad_lab[32];
03581
03582 ASM_GENERATE_INTERNAL_LABEL (reg_start_lab, "LEHB", call_site_base + i);
03583 ASM_GENERATE_INTERNAL_LABEL (reg_end_lab, "LEHE", call_site_base + i);
03584
03585 if (cs->landing_pad)
03586 ASM_GENERATE_INTERNAL_LABEL (landing_pad_lab, "L",
03587 CODE_LABEL_NUMBER (cs->landing_pad));
03588
03589
03590
03591
03592
03593 #ifdef HAVE_AS_LEB128
03594 dw2_asm_output_delta_uleb128 (reg_start_lab, function_start_lab,
03595 "region %d start", i);
03596 dw2_asm_output_delta_uleb128 (reg_end_lab, reg_start_lab,
03597 "length");
03598 if (cs->landing_pad)
03599 dw2_asm_output_delta_uleb128 (landing_pad_lab, function_start_lab,
03600 "landing pad");
03601 else
03602 dw2_asm_output_data_uleb128 (0, "landing pad");
03603 #else
03604 dw2_asm_output_delta (4, reg_start_lab, function_start_lab,
03605 "region %d start", i);
03606 dw2_asm_output_delta (4, reg_end_lab, reg_start_lab, "length");
03607 if (cs->landing_pad)
03608 dw2_asm_output_delta (4, landing_pad_lab, function_start_lab,
03609 "landing pad");
03610 else
03611 dw2_asm_output_data (4, 0, "landing pad");
03612 #endif
03613 dw2_asm_output_data_uleb128 (cs->action, "action");
03614 }
03615
03616 call_site_base += n;
03617 }
03618
03619 static void
03620 sjlj_output_call_site_table ()
03621 {
03622 int n = cfun->eh->call_site_data_used;
03623 int i;
03624
03625 for (i = 0; i < n; ++i)
03626 {
03627 struct call_site_record *cs = &cfun->eh->call_site_data[i];
03628
03629 dw2_asm_output_data_uleb128 (INTVAL (cs->landing_pad),
03630 "region %d landing pad", i);
03631 dw2_asm_output_data_uleb128 (cs->action, "action");
03632 }
03633
03634 call_site_base += n;
03635 }
03636
03637
03638
03639
03640 void
03641 default_exception_section ()
03642 {
03643 if (targetm.have_named_sections)
03644 {
03645 int flags;
03646 #ifdef HAVE_LD_RO_RW_SECTION_MIXING
03647 int tt_format = ASM_PREFERRED_EH_DATA_FORMAT (0, 1);
03648
03649 flags = (! flag_pic
03650 || ((tt_format & 0x70) != DW_EH_PE_absptr
03651 && (tt_format & 0x70) != DW_EH_PE_aligned))
03652 ? 0 : SECTION_WRITE;
03653 #else
03654 flags = SECTION_WRITE;
03655 #endif
03656 named_section_flags (".gcc_except_table", flags);
03657 }
03658 else if (flag_pic)
03659 data_section ();
03660 else
03661 readonly_data_section ();
03662 }
03663
03664 void
03665 output_function_exception_table ()
03666 {
03667 int tt_format, cs_format, lp_format, i, n;
03668 #ifdef HAVE_AS_LEB128
03669 char ttype_label[32];
03670 char cs_after_size_label[32];
03671 char cs_end_label[32];
03672 #else
03673 int call_site_len;
03674 #endif
03675 int have_tt_data;
03676 int tt_format_size = 0;
03677
03678
03679 if (! cfun->uses_eh_lsda)
03680 return;
03681
03682 #ifdef IA64_UNWIND_INFO
03683 fputs ("\t.personality\t", asm_out_file);
03684 output_addr_const (asm_out_file, eh_personality_libfunc);
03685 fputs ("\n\t.handlerdata\n", asm_out_file);
03686
03687
03688 #else
03689 (*targetm.asm_out.exception_section) ();
03690 #endif
03691
03692 have_tt_data = (VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data) > 0
03693 || VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data) > 0);
03694
03695
03696 if (! have_tt_data)
03697 tt_format = DW_EH_PE_omit;
03698 else
03699 {
03700 tt_format = ASM_PREFERRED_EH_DATA_FORMAT (0, 1);
03701 #ifdef HAVE_AS_LEB128
03702 ASM_GENERATE_INTERNAL_LABEL (ttype_label, "LLSDATT",
03703 current_function_funcdef_no);
03704 #endif
03705 tt_format_size = size_of_encoded_value (tt_format);
03706
03707 assemble_align (tt_format_size * BITS_PER_UNIT);
03708 }
03709
03710 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LLSDA",
03711 current_function_funcdef_no);
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721 lp_format = DW_EH_PE_omit;
03722 dw2_asm_output_data (1, lp_format, "@LPStart format (%s)",
03723 eh_data_format_name (lp_format));
03724
03725
03726
03727 dw2_asm_output_data (1, tt_format, "@TType format (%s)",
03728 eh_data_format_name (tt_format));
03729
03730 #ifndef HAVE_AS_LEB128
03731 if (USING_SJLJ_EXCEPTIONS)
03732 call_site_len = sjlj_size_of_call_site_table ();
03733 else
03734 call_site_len = dw2_size_of_call_site_table ();
03735 #endif
03736
03737
03738 if (have_tt_data)
03739 {
03740 #ifdef HAVE_AS_LEB128
03741 char ttype_after_disp_label[32];
03742 ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label, "LLSDATTD",
03743 current_function_funcdef_no);
03744 dw2_asm_output_delta_uleb128 (ttype_label, ttype_after_disp_label,
03745 "@TType base offset");
03746 ASM_OUTPUT_LABEL (asm_out_file, ttype_after_disp_label);
03747 #else
03748
03749 unsigned int before_disp, after_disp, last_disp, disp;
03750
03751 before_disp = 1 + 1;
03752 after_disp = (1 + size_of_uleb128 (call_site_len)
03753 + call_site_len
03754 + VARRAY_ACTIVE_SIZE (cfun->eh->action_record_data)
03755 + (VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data)
03756 * tt_format_size));
03757
03758 disp = after_disp;
03759 do
03760 {
03761 unsigned int disp_size, pad;
03762
03763 last_disp = disp;
03764 disp_size = size_of_uleb128 (disp);
03765 pad = before_disp + disp_size + after_disp;
03766 if (pad % tt_format_size)
03767 pad = tt_format_size - (pad % tt_format_size);
03768 else
03769 pad = 0;
03770 disp = after_disp + pad;
03771 }
03772 while (disp != last_disp);
03773
03774 dw2_asm_output_data_uleb128 (disp, "@TType base offset");
03775 #endif
03776 }
03777
03778
03779 #ifdef HAVE_AS_LEB128
03780 cs_format = DW_EH_PE_uleb128;
03781 #else
03782 cs_format = DW_EH_PE_udata4;
03783 #endif
03784 dw2_asm_output_data (1, cs_format, "call-site format (%s)",
03785 eh_data_format_name (cs_format));
03786
03787 #ifdef HAVE_AS_LEB128
03788 ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label, "LLSDACSB",
03789 current_function_funcdef_no);
03790 ASM_GENERATE_INTERNAL_LABEL (cs_end_label, "LLSDACSE",
03791 current_function_funcdef_no);
03792 dw2_asm_output_delta_uleb128 (cs_end_label, cs_after_size_label,
03793 "Call-site table length");
03794 ASM_OUTPUT_LABEL (asm_out_file, cs_after_size_label);
03795 if (USING_SJLJ_EXCEPTIONS)
03796 sjlj_output_call_site_table ();
03797 else
03798 dw2_output_call_site_table ();
03799 ASM_OUTPUT_LABEL (asm_out_file, cs_end_label);
03800 #else
03801 dw2_asm_output_data_uleb128 (call_site_len,"Call-site table length");
03802 if (USING_SJLJ_EXCEPTIONS)
03803 sjlj_output_call_site_table ();
03804 else
03805 dw2_output_call_site_table ();
03806 #endif
03807
03808
03809 n = VARRAY_ACTIVE_SIZE (cfun->eh->action_record_data);
03810 for (i = 0; i < n; ++i)
03811 dw2_asm_output_data (1, VARRAY_UCHAR (cfun->eh->action_record_data, i),
03812 (i ? NULL : "Action record table"));
03813
03814 if (have_tt_data)
03815 assemble_align (tt_format_size * BITS_PER_UNIT);
03816
03817 i = VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data);
03818 while (i-- > 0)
03819 {
03820 tree type = VARRAY_TREE (cfun->eh->ttype_data, i);
03821 rtx value;
03822
03823 if (type == NULL_TREE)
03824 type = integer_zero_node;
03825 else
03826 type = lookup_type_for_runtime (type);
03827
03828 value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
03829 if (tt_format == DW_EH_PE_absptr || tt_format == DW_EH_PE_aligned)
03830 assemble_integer (value, tt_format_size,
03831 tt_format_size * BITS_PER_UNIT, 1);
03832 else
03833 dw2_asm_output_encoded_addr_rtx (tt_format, value, NULL);
03834 }
03835
03836 #ifdef HAVE_AS_LEB128
03837 if (have_tt_data)
03838 ASM_OUTPUT_LABEL (asm_out_file, ttype_label);
03839 #endif
03840
03841
03842 n = VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data);
03843 for (i = 0; i < n; ++i)
03844 dw2_asm_output_data (1, VARRAY_UCHAR (cfun->eh->ehspec_data, i),
03845 (i ? NULL : "Exception specification table"));
03846
03847 function_section (current_function_decl);
03848 }
03849
03850 #include "gt-except.h"