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