OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [except.c] - Blame information for rev 826

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 280 jeremybenn
/* Implements exception handling.
2
   Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3
   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4
   Free Software Foundation, Inc.
5
   Contributed by Mike Stump <mrs@cygnus.com>.
6
 
7
This file is part of GCC.
8
 
9
GCC is free software; you can redistribute it and/or modify it under
10
the terms of the GNU General Public License as published by the Free
11
Software Foundation; either version 3, or (at your option) any later
12
version.
13
 
14
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15
WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17
for more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with GCC; see the file COPYING3.  If not see
21
<http://www.gnu.org/licenses/>.  */
22
 
23
 
24
/* An exception is an event that can be "thrown" from within a
25
   function.  This event can then be "caught" by the callers of
26
   the function.
27
 
28
   The representation of exceptions changes several times during
29
   the compilation process:
30
 
31
   In the beginning, in the front end, we have the GENERIC trees
32
   TRY_CATCH_EXPR, TRY_FINALLY_EXPR, WITH_CLEANUP_EXPR,
33
   CLEANUP_POINT_EXPR, CATCH_EXPR, and EH_FILTER_EXPR.
34
 
35
   During initial gimplification (gimplify.c) these are lowered
36
   to the GIMPLE_TRY, GIMPLE_CATCH, and GIMPLE_EH_FILTER nodes.
37
   The WITH_CLEANUP_EXPR and CLEANUP_POINT_EXPR nodes are converted
38
   into GIMPLE_TRY_FINALLY nodes; the others are a more direct 1-1
39
   conversion.
40
 
41
   During pass_lower_eh (tree-eh.c) we record the nested structure
42
   of the TRY nodes in EH_REGION nodes in CFUN->EH->REGION_TREE.
43
   We expand the lang_protect_cleanup_actions hook into MUST_NOT_THROW
44
   regions at this time.  We can then flatten the statements within
45
   the TRY nodes to straight-line code.  Statements that had been within
46
   TRY nodes that can throw are recorded within CFUN->EH->THROW_STMT_TABLE,
47
   so that we may remember what action is supposed to be taken if
48
   a given statement does throw.  During this lowering process,
49
   we create an EH_LANDING_PAD node for each EH_REGION that has
50
   some code within the function that needs to be executed if a
51
   throw does happen.  We also create RESX statements that are
52
   used to transfer control from an inner EH_REGION to an outer
53
   EH_REGION.  We also create EH_DISPATCH statements as placeholders
54
   for a runtime type comparison that should be made in order to
55
   select the action to perform among different CATCH and EH_FILTER
56
   regions.
57
 
58
   During pass_lower_eh_dispatch (tree-eh.c), which is run after
59
   all inlining is complete, we are able to run assign_filter_values,
60
   which allows us to map the set of types manipulated by all of the
61
   CATCH and EH_FILTER regions to a set of integers.  This set of integers
62
   will be how the exception runtime communicates with the code generated
63
   within the function.  We then expand the GIMPLE_EH_DISPATCH statements
64
   to a switch or conditional branches that use the argument provided by
65
   the runtime (__builtin_eh_filter) and the set of integers we computed
66
   in assign_filter_values.
67
 
68
   During pass_lower_resx (tree-eh.c), which is run near the end
69
   of optimization, we expand RESX statements.  If the eh region
70
   that is outer to the RESX statement is a MUST_NOT_THROW, then
71
   the RESX expands to some form of abort statement.  If the eh
72
   region that is outer to the RESX statement is within the current
73
   function, then the RESX expands to a bookkeeping call
74
   (__builtin_eh_copy_values) and a goto.  Otherwise, the next
75
   handler for the exception must be within a function somewhere
76
   up the call chain, so we call back into the exception runtime
77
   (__builtin_unwind_resume).
78
 
79
   During pass_expand (cfgexpand.c), we generate REG_EH_REGION notes
80
   that create an rtl to eh_region mapping that corresponds to the
81
   gimple to eh_region mapping that had been recorded in the
82
   THROW_STMT_TABLE.
83
 
84
   During pass_rtl_eh (except.c), we generate the real landing pads
85
   to which the runtime will actually transfer control.  These new
86
   landing pads perform whatever bookkeeping is needed by the target
87
   backend in order to resume execution within the current function.
88
   Each of these new landing pads falls through into the post_landing_pad
89
   label which had been used within the CFG up to this point.  All
90
   exception edges within the CFG are redirected to the new landing pads.
91
   If the target uses setjmp to implement exceptions, the various extra
92
   calls into the runtime to register and unregister the current stack
93
   frame are emitted at this time.
94
 
95
   During pass_convert_to_eh_region_ranges (except.c), we transform
96
   the REG_EH_REGION notes attached to individual insns into
97
   non-overlapping ranges of insns bounded by NOTE_INSN_EH_REGION_BEG
98
   and NOTE_INSN_EH_REGION_END.  Each insn within such ranges has the
99
   same associated action within the exception region tree, meaning
100
   that (1) the exception is caught by the same landing pad within the
101
   current function, (2) the exception is blocked by the runtime with
102
   a MUST_NOT_THROW region, or (3) the exception is not handled at all
103
   within the current function.
104
 
105
   Finally, during assembly generation, we call
106
   output_function_exception_table (except.c) to emit the tables with
107
   which the exception runtime can determine if a given stack frame
108
   handles a given exception, and if so what filter value to provide
109
   to the function when the non-local control transfer is effected.
110
   If the target uses dwarf2 unwinding to implement exceptions, then
111
   output_call_frame_info (dwarf2out.c) emits the required unwind data.  */
112
 
113
 
114
#include "config.h"
115
#include "system.h"
116
#include "coretypes.h"
117
#include "tm.h"
118
#include "rtl.h"
119
#include "tree.h"
120
#include "flags.h"
121
#include "function.h"
122
#include "expr.h"
123
#include "libfuncs.h"
124
#include "insn-config.h"
125
#include "except.h"
126
#include "integrate.h"
127
#include "hard-reg-set.h"
128
#include "basic-block.h"
129
#include "output.h"
130
#include "dwarf2asm.h"
131
#include "dwarf2out.h"
132
#include "dwarf2.h"
133
#include "toplev.h"
134
#include "hashtab.h"
135
#include "intl.h"
136
#include "ggc.h"
137
#include "tm_p.h"
138
#include "target.h"
139
#include "langhooks.h"
140
#include "cgraph.h"
141
#include "diagnostic.h"
142
#include "tree-pass.h"
143
#include "timevar.h"
144
#include "tree-flow.h"
145
 
146
/* Provide defaults for stuff that may not be defined when using
147
   sjlj exceptions.  */
148
#ifndef EH_RETURN_DATA_REGNO
149
#define EH_RETURN_DATA_REGNO(N) INVALID_REGNUM
150
#endif
151
 
152
/* Protect cleanup actions with must-not-throw regions, with a call
153
   to the given failure handler.  */
154
tree (*lang_protect_cleanup_actions) (void);
155
 
156
/* Return true if type A catches type B.  */
157
int (*lang_eh_type_covers) (tree a, tree b);
158
 
159
static GTY(()) int call_site_base;
160
static GTY ((param_is (union tree_node)))
161
  htab_t type_to_runtime_map;
162
 
163
/* Describe the SjLj_Function_Context structure.  */
164
static GTY(()) tree sjlj_fc_type_node;
165
static int sjlj_fc_call_site_ofs;
166
static int sjlj_fc_data_ofs;
167
static int sjlj_fc_personality_ofs;
168
static int sjlj_fc_lsda_ofs;
169
static int sjlj_fc_jbuf_ofs;
170
 
171
 
172
struct GTY(()) call_site_record_d
173
{
174
  rtx landing_pad;
175
  int action;
176
};
177
 
178
static bool get_eh_region_and_lp_from_rtx (const_rtx, eh_region *,
179
                                           eh_landing_pad *);
180
 
181
static int t2r_eq (const void *, const void *);
182
static hashval_t t2r_hash (const void *);
183
 
184
static int ttypes_filter_eq (const void *, const void *);
185
static hashval_t ttypes_filter_hash (const void *);
186
static int ehspec_filter_eq (const void *, const void *);
187
static hashval_t ehspec_filter_hash (const void *);
188
static int add_ttypes_entry (htab_t, tree);
189
static int add_ehspec_entry (htab_t, htab_t, tree);
190
static void dw2_build_landing_pads (void);
191
 
192
static int action_record_eq (const void *, const void *);
193
static hashval_t action_record_hash (const void *);
194
static int add_action_record (htab_t, int, int);
195
static int collect_one_action_chain (htab_t, eh_region);
196
static int add_call_site (rtx, int, int);
197
 
198
static void push_uleb128 (VEC (uchar, gc) **, unsigned int);
199
static void push_sleb128 (VEC (uchar, gc) **, int);
200
#ifndef HAVE_AS_LEB128
201
static int dw2_size_of_call_site_table (int);
202
static int sjlj_size_of_call_site_table (void);
203
#endif
204
static void dw2_output_call_site_table (int, int);
205
static void sjlj_output_call_site_table (void);
206
 
207
 
208
/* Routine to see if exception handling is turned on.
209
   DO_WARN is nonzero if we want to inform the user that exception
210
   handling is turned off.
211
 
212
   This is used to ensure that -fexceptions has been specified if the
213
   compiler tries to use any exception-specific functions.  */
214
 
215
int
216
doing_eh (int do_warn)
217
{
218
  if (! flag_exceptions)
219
    {
220
      static int warned = 0;
221
      if (! warned && do_warn)
222
        {
223
          error ("exception handling disabled, use -fexceptions to enable");
224
          warned = 1;
225
        }
226
      return 0;
227
    }
228
  return 1;
229
}
230
 
231
 
232
void
233
init_eh (void)
234
{
235
  if (! flag_exceptions)
236
    return;
237
 
238
  type_to_runtime_map = htab_create_ggc (31, t2r_hash, t2r_eq, NULL);
239
 
240
  /* Create the SjLj_Function_Context structure.  This should match
241
     the definition in unwind-sjlj.c.  */
242
  if (USING_SJLJ_EXCEPTIONS)
243
    {
244
      tree f_jbuf, f_per, f_lsda, f_prev, f_cs, f_data, tmp;
245
 
246
      sjlj_fc_type_node = lang_hooks.types.make_type (RECORD_TYPE);
247
 
248
      f_prev = build_decl (BUILTINS_LOCATION,
249
                           FIELD_DECL, get_identifier ("__prev"),
250
                           build_pointer_type (sjlj_fc_type_node));
251
      DECL_FIELD_CONTEXT (f_prev) = sjlj_fc_type_node;
252
 
253
      f_cs = build_decl (BUILTINS_LOCATION,
254
                         FIELD_DECL, get_identifier ("__call_site"),
255
                         integer_type_node);
256
      DECL_FIELD_CONTEXT (f_cs) = sjlj_fc_type_node;
257
 
258
      tmp = build_index_type (build_int_cst (NULL_TREE, 4 - 1));
259
      tmp = build_array_type (lang_hooks.types.type_for_mode
260
                                (targetm.unwind_word_mode (), 1),
261
                              tmp);
262
      f_data = build_decl (BUILTINS_LOCATION,
263
                           FIELD_DECL, get_identifier ("__data"), tmp);
264
      DECL_FIELD_CONTEXT (f_data) = sjlj_fc_type_node;
265
 
266
      f_per = build_decl (BUILTINS_LOCATION,
267
                          FIELD_DECL, get_identifier ("__personality"),
268
                          ptr_type_node);
269
      DECL_FIELD_CONTEXT (f_per) = sjlj_fc_type_node;
270
 
271
      f_lsda = build_decl (BUILTINS_LOCATION,
272
                           FIELD_DECL, get_identifier ("__lsda"),
273
                           ptr_type_node);
274
      DECL_FIELD_CONTEXT (f_lsda) = sjlj_fc_type_node;
275
 
276
#ifdef DONT_USE_BUILTIN_SETJMP
277
#ifdef JMP_BUF_SIZE
278
      tmp = build_int_cst (NULL_TREE, JMP_BUF_SIZE - 1);
279
#else
280
      /* Should be large enough for most systems, if it is not,
281
         JMP_BUF_SIZE should be defined with the proper value.  It will
282
         also tend to be larger than necessary for most systems, a more
283
         optimal port will define JMP_BUF_SIZE.  */
284
      tmp = build_int_cst (NULL_TREE, FIRST_PSEUDO_REGISTER + 2 - 1);
285
#endif
286
#else
287
      /* builtin_setjmp takes a pointer to 5 words.  */
288
      tmp = build_int_cst (NULL_TREE, 5 * BITS_PER_WORD / POINTER_SIZE - 1);
289
#endif
290
      tmp = build_index_type (tmp);
291
      tmp = build_array_type (ptr_type_node, tmp);
292
      f_jbuf = build_decl (BUILTINS_LOCATION,
293
                           FIELD_DECL, get_identifier ("__jbuf"), tmp);
294
#ifdef DONT_USE_BUILTIN_SETJMP
295
      /* We don't know what the alignment requirements of the
296
         runtime's jmp_buf has.  Overestimate.  */
297
      DECL_ALIGN (f_jbuf) = BIGGEST_ALIGNMENT;
298
      DECL_USER_ALIGN (f_jbuf) = 1;
299
#endif
300
      DECL_FIELD_CONTEXT (f_jbuf) = sjlj_fc_type_node;
301
 
302
      TYPE_FIELDS (sjlj_fc_type_node) = f_prev;
303
      TREE_CHAIN (f_prev) = f_cs;
304
      TREE_CHAIN (f_cs) = f_data;
305
      TREE_CHAIN (f_data) = f_per;
306
      TREE_CHAIN (f_per) = f_lsda;
307
      TREE_CHAIN (f_lsda) = f_jbuf;
308
 
309
      layout_type (sjlj_fc_type_node);
310
 
311
      /* Cache the interesting field offsets so that we have
312
         easy access from rtl.  */
313
      sjlj_fc_call_site_ofs
314
        = (tree_low_cst (DECL_FIELD_OFFSET (f_cs), 1)
315
           + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_cs), 1) / BITS_PER_UNIT);
316
      sjlj_fc_data_ofs
317
        = (tree_low_cst (DECL_FIELD_OFFSET (f_data), 1)
318
           + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_data), 1) / BITS_PER_UNIT);
319
      sjlj_fc_personality_ofs
320
        = (tree_low_cst (DECL_FIELD_OFFSET (f_per), 1)
321
           + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_per), 1) / BITS_PER_UNIT);
322
      sjlj_fc_lsda_ofs
323
        = (tree_low_cst (DECL_FIELD_OFFSET (f_lsda), 1)
324
           + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_lsda), 1) / BITS_PER_UNIT);
325
      sjlj_fc_jbuf_ofs
326
        = (tree_low_cst (DECL_FIELD_OFFSET (f_jbuf), 1)
327
           + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_jbuf), 1) / BITS_PER_UNIT);
328
    }
329
}
330
 
331
void
332
init_eh_for_function (void)
333
{
334
  cfun->eh = GGC_CNEW (struct eh_status);
335
 
336
  /* Make sure zero'th entries are used.  */
337
  VEC_safe_push (eh_region, gc, cfun->eh->region_array, NULL);
338
  VEC_safe_push (eh_landing_pad, gc, cfun->eh->lp_array, NULL);
339
}
340
 
341
/* Routines to generate the exception tree somewhat directly.
342
   These are used from tree-eh.c when processing exception related
343
   nodes during tree optimization.  */
344
 
345
static eh_region
346
gen_eh_region (enum eh_region_type type, eh_region outer)
347
{
348
  eh_region new_eh;
349
 
350
#ifdef ENABLE_CHECKING
351
  gcc_assert (doing_eh (0));
352
#endif
353
 
354
  /* Insert a new blank region as a leaf in the tree.  */
355
  new_eh = GGC_CNEW (struct eh_region_d);
356
  new_eh->type = type;
357
  new_eh->outer = outer;
358
  if (outer)
359
    {
360
      new_eh->next_peer = outer->inner;
361
      outer->inner = new_eh;
362
    }
363
  else
364
    {
365
      new_eh->next_peer = cfun->eh->region_tree;
366
      cfun->eh->region_tree = new_eh;
367
    }
368
 
369
  new_eh->index = VEC_length (eh_region, cfun->eh->region_array);
370
  VEC_safe_push (eh_region, gc, cfun->eh->region_array, new_eh);
371
 
372
  /* Copy the language's notion of whether to use __cxa_end_cleanup.  */
373
  if (targetm.arm_eabi_unwinder && lang_hooks.eh_use_cxa_end_cleanup)
374
    new_eh->use_cxa_end_cleanup = true;
375
 
376
  return new_eh;
377
}
378
 
379
eh_region
380
gen_eh_region_cleanup (eh_region outer)
381
{
382
  return gen_eh_region (ERT_CLEANUP, outer);
383
}
384
 
385
eh_region
386
gen_eh_region_try (eh_region outer)
387
{
388
  return gen_eh_region (ERT_TRY, outer);
389
}
390
 
391
eh_catch
392
gen_eh_region_catch (eh_region t, tree type_or_list)
393
{
394
  eh_catch c, l;
395
  tree type_list, type_node;
396
 
397
  gcc_assert (t->type == ERT_TRY);
398
 
399
  /* Ensure to always end up with a type list to normalize further
400
     processing, then register each type against the runtime types map.  */
401
  type_list = type_or_list;
402
  if (type_or_list)
403
    {
404
      if (TREE_CODE (type_or_list) != TREE_LIST)
405
        type_list = tree_cons (NULL_TREE, type_or_list, NULL_TREE);
406
 
407
      type_node = type_list;
408
      for (; type_node; type_node = TREE_CHAIN (type_node))
409
        add_type_for_runtime (TREE_VALUE (type_node));
410
    }
411
 
412
  c = GGC_CNEW (struct eh_catch_d);
413
  c->type_list = type_list;
414
  l = t->u.eh_try.last_catch;
415
  c->prev_catch = l;
416
  if (l)
417
    l->next_catch = c;
418
  else
419
    t->u.eh_try.first_catch = c;
420
  t->u.eh_try.last_catch = c;
421
 
422
  return c;
423
}
424
 
425
eh_region
426
gen_eh_region_allowed (eh_region outer, tree allowed)
427
{
428
  eh_region region = gen_eh_region (ERT_ALLOWED_EXCEPTIONS, outer);
429
  region->u.allowed.type_list = allowed;
430
 
431
  for (; allowed ; allowed = TREE_CHAIN (allowed))
432
    add_type_for_runtime (TREE_VALUE (allowed));
433
 
434
  return region;
435
}
436
 
437
eh_region
438
gen_eh_region_must_not_throw (eh_region outer)
439
{
440
  return gen_eh_region (ERT_MUST_NOT_THROW, outer);
441
}
442
 
443
eh_landing_pad
444
gen_eh_landing_pad (eh_region region)
445
{
446
  eh_landing_pad lp = GGC_CNEW (struct eh_landing_pad_d);
447
 
448
  lp->next_lp = region->landing_pads;
449
  lp->region = region;
450
  lp->index = VEC_length (eh_landing_pad, cfun->eh->lp_array);
451
  region->landing_pads = lp;
452
 
453
  VEC_safe_push (eh_landing_pad, gc, cfun->eh->lp_array, lp);
454
 
455
  return lp;
456
}
457
 
458
eh_region
459
get_eh_region_from_number_fn (struct function *ifun, int i)
460
{
461
  return VEC_index (eh_region, ifun->eh->region_array, i);
462
}
463
 
464
eh_region
465
get_eh_region_from_number (int i)
466
{
467
  return get_eh_region_from_number_fn (cfun, i);
468
}
469
 
470
eh_landing_pad
471
get_eh_landing_pad_from_number_fn (struct function *ifun, int i)
472
{
473
  return VEC_index (eh_landing_pad, ifun->eh->lp_array, i);
474
}
475
 
476
eh_landing_pad
477
get_eh_landing_pad_from_number (int i)
478
{
479
  return get_eh_landing_pad_from_number_fn (cfun, i);
480
}
481
 
482
eh_region
483
get_eh_region_from_lp_number_fn (struct function *ifun, int i)
484
{
485
  if (i < 0)
486
    return VEC_index (eh_region, ifun->eh->region_array, -i);
487
  else if (i == 0)
488
    return NULL;
489
  else
490
    {
491
      eh_landing_pad lp;
492
      lp = VEC_index (eh_landing_pad, ifun->eh->lp_array, i);
493
      return lp->region;
494
    }
495
}
496
 
497
eh_region
498
get_eh_region_from_lp_number (int i)
499
{
500
  return get_eh_region_from_lp_number_fn (cfun, i);
501
}
502
 
503
/* Returns true if the current function has exception handling regions.  */
504
 
505
bool
506
current_function_has_exception_handlers (void)
507
{
508
  return cfun->eh->region_tree != NULL;
509
}
510
 
511
/* A subroutine of duplicate_eh_regions.  Copy the eh_region tree at OLD.
512
   Root it at OUTER, and apply LP_OFFSET to the lp numbers.  */
513
 
514
struct duplicate_eh_regions_data
515
{
516
  duplicate_eh_regions_map label_map;
517
  void *label_map_data;
518
  struct pointer_map_t *eh_map;
519
};
520
 
521
static void
522
duplicate_eh_regions_1 (struct duplicate_eh_regions_data *data,
523
                        eh_region old_r, eh_region outer)
524
{
525
  eh_landing_pad old_lp, new_lp;
526
  eh_region new_r;
527
  void **slot;
528
 
529
  new_r = gen_eh_region (old_r->type, outer);
530
  slot = pointer_map_insert (data->eh_map, (void *)old_r);
531
  gcc_assert (*slot == NULL);
532
  *slot = (void *)new_r;
533
 
534
  switch (old_r->type)
535
    {
536
    case ERT_CLEANUP:
537
      break;
538
 
539
    case ERT_TRY:
540
      {
541
        eh_catch oc, nc;
542
        for (oc = old_r->u.eh_try.first_catch; oc ; oc = oc->next_catch)
543
          {
544
            /* We should be doing all our region duplication before and
545
               during inlining, which is before filter lists are created.  */
546
            gcc_assert (oc->filter_list == NULL);
547
            nc = gen_eh_region_catch (new_r, oc->type_list);
548
            nc->label = data->label_map (oc->label, data->label_map_data);
549
          }
550
      }
551
      break;
552
 
553
    case ERT_ALLOWED_EXCEPTIONS:
554
      new_r->u.allowed.type_list = old_r->u.allowed.type_list;
555
      if (old_r->u.allowed.label)
556
        new_r->u.allowed.label
557
            = data->label_map (old_r->u.allowed.label, data->label_map_data);
558
      else
559
        new_r->u.allowed.label = NULL_TREE;
560
      break;
561
 
562
    case ERT_MUST_NOT_THROW:
563
      new_r->u.must_not_throw = old_r->u.must_not_throw;
564
      break;
565
    }
566
 
567
  for (old_lp = old_r->landing_pads; old_lp ; old_lp = old_lp->next_lp)
568
    {
569
      /* Don't bother copying unused landing pads.  */
570
      if (old_lp->post_landing_pad == NULL)
571
        continue;
572
 
573
      new_lp = gen_eh_landing_pad (new_r);
574
      slot = pointer_map_insert (data->eh_map, (void *)old_lp);
575
      gcc_assert (*slot == NULL);
576
      *slot = (void *)new_lp;
577
 
578
      new_lp->post_landing_pad
579
        = data->label_map (old_lp->post_landing_pad, data->label_map_data);
580
      EH_LANDING_PAD_NR (new_lp->post_landing_pad) = new_lp->index;
581
    }
582
 
583
  /* Make sure to preserve the original use of __cxa_end_cleanup.  */
584
  new_r->use_cxa_end_cleanup = old_r->use_cxa_end_cleanup;
585
 
586
  for (old_r = old_r->inner; old_r ; old_r = old_r->next_peer)
587
    duplicate_eh_regions_1 (data, old_r, new_r);
588
}
589
 
590
/* Duplicate the EH regions from IFUN rooted at COPY_REGION into
591
   the current function and root the tree below OUTER_REGION.
592
   The special case of COPY_REGION of NULL means all regions.
593
   Remap labels using MAP/MAP_DATA callback.  Return a pointer map
594
   that allows the caller to remap uses of both EH regions and
595
   EH landing pads.  */
596
 
597
struct pointer_map_t *
598
duplicate_eh_regions (struct function *ifun,
599
                      eh_region copy_region, int outer_lp,
600
                      duplicate_eh_regions_map map, void *map_data)
601
{
602
  struct duplicate_eh_regions_data data;
603
  eh_region outer_region;
604
 
605
#ifdef ENABLE_CHECKING
606
  verify_eh_tree (ifun);
607
#endif
608
 
609
  data.label_map = map;
610
  data.label_map_data = map_data;
611
  data.eh_map = pointer_map_create ();
612
 
613
  outer_region = get_eh_region_from_lp_number (outer_lp);
614
 
615
  /* Copy all the regions in the subtree.  */
616
  if (copy_region)
617
    duplicate_eh_regions_1 (&data, copy_region, outer_region);
618
  else
619
    {
620
      eh_region r;
621
      for (r = ifun->eh->region_tree; r ; r = r->next_peer)
622
        duplicate_eh_regions_1 (&data, r, outer_region);
623
    }
624
 
625
#ifdef ENABLE_CHECKING
626
  verify_eh_tree (cfun);
627
#endif
628
 
629
  return data.eh_map;
630
}
631
 
632
/* Return the region that is outer to both REGION_A and REGION_B in IFUN.  */
633
 
634
eh_region
635
eh_region_outermost (struct function *ifun, eh_region region_a,
636
                     eh_region region_b)
637
{
638
  sbitmap b_outer;
639
 
640
  gcc_assert (ifun->eh->region_array);
641
  gcc_assert (ifun->eh->region_tree);
642
 
643
  b_outer = sbitmap_alloc (VEC_length (eh_region, ifun->eh->region_array));
644
  sbitmap_zero (b_outer);
645
 
646
  do
647
    {
648
      SET_BIT (b_outer, region_b->index);
649
      region_b = region_b->outer;
650
    }
651
  while (region_b);
652
 
653
  do
654
    {
655
      if (TEST_BIT (b_outer, region_a->index))
656
        break;
657
      region_a = region_a->outer;
658
    }
659
  while (region_a);
660
 
661
  sbitmap_free (b_outer);
662
  return region_a;
663
}
664
 
665
static int
666
t2r_eq (const void *pentry, const void *pdata)
667
{
668
  const_tree const entry = (const_tree) pentry;
669
  const_tree const data = (const_tree) pdata;
670
 
671
  return TREE_PURPOSE (entry) == data;
672
}
673
 
674
static hashval_t
675
t2r_hash (const void *pentry)
676
{
677
  const_tree const entry = (const_tree) pentry;
678
  return TREE_HASH (TREE_PURPOSE (entry));
679
}
680
 
681
void
682
add_type_for_runtime (tree type)
683
{
684
  tree *slot;
685
 
686
  /* If TYPE is NOP_EXPR, it means that it already is a runtime type.  */
687
  if (TREE_CODE (type) == NOP_EXPR)
688
    return;
689
 
690
  slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type,
691
                                            TREE_HASH (type), INSERT);
692
  if (*slot == NULL)
693
    {
694
      tree runtime = lang_hooks.eh_runtime_type (type);
695
      *slot = tree_cons (type, runtime, NULL_TREE);
696
    }
697
}
698
 
699
tree
700
lookup_type_for_runtime (tree type)
701
{
702
  tree *slot;
703
 
704
  /* If TYPE is NOP_EXPR, it means that it already is a runtime type.  */
705
  if (TREE_CODE (type) == NOP_EXPR)
706
    return type;
707
 
708
  slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type,
709
                                            TREE_HASH (type), NO_INSERT);
710
 
711
  /* We should have always inserted the data earlier.  */
712
  return TREE_VALUE (*slot);
713
}
714
 
715
 
716
/* Represent an entry in @TTypes for either catch actions
717
   or exception filter actions.  */
718
struct GTY(()) ttypes_filter {
719
  tree t;
720
  int filter;
721
};
722
 
723
/* Compare ENTRY (a ttypes_filter entry in the hash table) with DATA
724
   (a tree) for a @TTypes type node we are thinking about adding.  */
725
 
726
static int
727
ttypes_filter_eq (const void *pentry, const void *pdata)
728
{
729
  const struct ttypes_filter *const entry
730
    = (const struct ttypes_filter *) pentry;
731
  const_tree const data = (const_tree) pdata;
732
 
733
  return entry->t == data;
734
}
735
 
736
static hashval_t
737
ttypes_filter_hash (const void *pentry)
738
{
739
  const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
740
  return TREE_HASH (entry->t);
741
}
742
 
743
/* Compare ENTRY with DATA (both struct ttypes_filter) for a @TTypes
744
   exception specification list we are thinking about adding.  */
745
/* ??? Currently we use the type lists in the order given.  Someone
746
   should put these in some canonical order.  */
747
 
748
static int
749
ehspec_filter_eq (const void *pentry, const void *pdata)
750
{
751
  const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
752
  const struct ttypes_filter *data = (const struct ttypes_filter *) pdata;
753
 
754
  return type_list_equal (entry->t, data->t);
755
}
756
 
757
/* Hash function for exception specification lists.  */
758
 
759
static hashval_t
760
ehspec_filter_hash (const void *pentry)
761
{
762
  const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
763
  hashval_t h = 0;
764
  tree list;
765
 
766
  for (list = entry->t; list ; list = TREE_CHAIN (list))
767
    h = (h << 5) + (h >> 27) + TREE_HASH (TREE_VALUE (list));
768
  return h;
769
}
770
 
771
/* Add TYPE (which may be NULL) to cfun->eh->ttype_data, using TYPES_HASH
772
   to speed up the search.  Return the filter value to be used.  */
773
 
774
static int
775
add_ttypes_entry (htab_t ttypes_hash, tree type)
776
{
777
  struct ttypes_filter **slot, *n;
778
 
779
  slot = (struct ttypes_filter **)
780
    htab_find_slot_with_hash (ttypes_hash, type, TREE_HASH (type), INSERT);
781
 
782
  if ((n = *slot) == NULL)
783
    {
784
      /* Filter value is a 1 based table index.  */
785
 
786
      n = XNEW (struct ttypes_filter);
787
      n->t = type;
788
      n->filter = VEC_length (tree, cfun->eh->ttype_data) + 1;
789
      *slot = n;
790
 
791
      VEC_safe_push (tree, gc, cfun->eh->ttype_data, type);
792
    }
793
 
794
  return n->filter;
795
}
796
 
797
/* Add LIST to cfun->eh->ehspec_data, using EHSPEC_HASH and TYPES_HASH
798
   to speed up the search.  Return the filter value to be used.  */
799
 
800
static int
801
add_ehspec_entry (htab_t ehspec_hash, htab_t ttypes_hash, tree list)
802
{
803
  struct ttypes_filter **slot, *n;
804
  struct ttypes_filter dummy;
805
 
806
  dummy.t = list;
807
  slot = (struct ttypes_filter **)
808
    htab_find_slot (ehspec_hash, &dummy, INSERT);
809
 
810
  if ((n = *slot) == NULL)
811
    {
812
      int len;
813
 
814
      if (targetm.arm_eabi_unwinder)
815
        len = VEC_length (tree, cfun->eh->ehspec_data.arm_eabi);
816
      else
817
        len = VEC_length (uchar, cfun->eh->ehspec_data.other);
818
 
819
      /* Filter value is a -1 based byte index into a uleb128 buffer.  */
820
 
821
      n = XNEW (struct ttypes_filter);
822
      n->t = list;
823
      n->filter = -(len + 1);
824
      *slot = n;
825
 
826
      /* Generate a 0 terminated list of filter values.  */
827
      for (; list ; list = TREE_CHAIN (list))
828
        {
829
          if (targetm.arm_eabi_unwinder)
830
            VEC_safe_push (tree, gc, cfun->eh->ehspec_data.arm_eabi,
831
                           TREE_VALUE (list));
832
          else
833
            {
834
              /* Look up each type in the list and encode its filter
835
                 value as a uleb128.  */
836
              push_uleb128 (&cfun->eh->ehspec_data.other,
837
                            add_ttypes_entry (ttypes_hash, TREE_VALUE (list)));
838
            }
839
        }
840
      if (targetm.arm_eabi_unwinder)
841
        VEC_safe_push (tree, gc, cfun->eh->ehspec_data.arm_eabi, NULL_TREE);
842
      else
843
        VEC_safe_push (uchar, gc, cfun->eh->ehspec_data.other, 0);
844
    }
845
 
846
  return n->filter;
847
}
848
 
849
/* Generate the action filter values to be used for CATCH and
850
   ALLOWED_EXCEPTIONS regions.  When using dwarf2 exception regions,
851
   we use lots of landing pads, and so every type or list can share
852
   the same filter value, which saves table space.  */
853
 
854
void
855
assign_filter_values (void)
856
{
857
  int i;
858
  htab_t ttypes, ehspec;
859
  eh_region r;
860
  eh_catch c;
861
 
862
  cfun->eh->ttype_data = VEC_alloc (tree, gc, 16);
863
  if (targetm.arm_eabi_unwinder)
864
    cfun->eh->ehspec_data.arm_eabi = VEC_alloc (tree, gc, 64);
865
  else
866
    cfun->eh->ehspec_data.other = VEC_alloc (uchar, gc, 64);
867
 
868
  ttypes = htab_create (31, ttypes_filter_hash, ttypes_filter_eq, free);
869
  ehspec = htab_create (31, ehspec_filter_hash, ehspec_filter_eq, free);
870
 
871
  for (i = 1; VEC_iterate (eh_region, cfun->eh->region_array, i, r); ++i)
872
    {
873
      if (r == NULL)
874
        continue;
875
 
876
      switch (r->type)
877
        {
878
        case ERT_TRY:
879
          for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
880
            {
881
              /* Whatever type_list is (NULL or true list), we build a list
882
                 of filters for the region.  */
883
              c->filter_list = NULL_TREE;
884
 
885
              if (c->type_list != NULL)
886
                {
887
                  /* Get a filter value for each of the types caught and store
888
                     them in the region's dedicated list.  */
889
                  tree tp_node = c->type_list;
890
 
891
                  for ( ; tp_node; tp_node = TREE_CHAIN (tp_node))
892
                    {
893
                      int flt = add_ttypes_entry (ttypes, TREE_VALUE (tp_node));
894
                      tree flt_node = build_int_cst (NULL_TREE, flt);
895
 
896
                      c->filter_list
897
                        = tree_cons (NULL_TREE, flt_node, c->filter_list);
898
                    }
899
                }
900
              else
901
                {
902
                  /* Get a filter value for the NULL list also since it
903
                     will need an action record anyway.  */
904
                  int flt = add_ttypes_entry (ttypes, NULL);
905
                  tree flt_node = build_int_cst (NULL_TREE, flt);
906
 
907
                  c->filter_list
908
                    = tree_cons (NULL_TREE, flt_node, NULL);
909
                }
910
            }
911
          break;
912
 
913
        case ERT_ALLOWED_EXCEPTIONS:
914
          r->u.allowed.filter
915
            = add_ehspec_entry (ehspec, ttypes, r->u.allowed.type_list);
916
          break;
917
 
918
        default:
919
          break;
920
        }
921
    }
922
 
923
  htab_delete (ttypes);
924
  htab_delete (ehspec);
925
}
926
 
927
/* Emit SEQ into basic block just before INSN (that is assumed to be
928
   first instruction of some existing BB and return the newly
929
   produced block.  */
930
static basic_block
931
emit_to_new_bb_before (rtx seq, rtx insn)
932
{
933
  rtx last;
934
  basic_block bb;
935
  edge e;
936
  edge_iterator ei;
937
 
938
  /* If there happens to be a fallthru edge (possibly created by cleanup_cfg
939
     call), we don't want it to go into newly created landing pad or other EH
940
     construct.  */
941
  for (ei = ei_start (BLOCK_FOR_INSN (insn)->preds); (e = ei_safe_edge (ei)); )
942
    if (e->flags & EDGE_FALLTHRU)
943
      force_nonfallthru (e);
944
    else
945
      ei_next (&ei);
946
  last = emit_insn_before (seq, insn);
947
  if (BARRIER_P (last))
948
    last = PREV_INSN (last);
949
  bb = create_basic_block (seq, last, BLOCK_FOR_INSN (insn)->prev_bb);
950
  update_bb_for_insn (bb);
951
  bb->flags |= BB_SUPERBLOCK;
952
  return bb;
953
}
954
 
955
/* Expand the extra code needed at landing pads for dwarf2 unwinding.  */
956
 
957
static void
958
dw2_build_landing_pads (void)
959
{
960
  int i;
961
  eh_landing_pad lp;
962
 
963
  for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
964
    {
965
      eh_region region;
966
      basic_block bb;
967
      rtx seq;
968
      edge e;
969
 
970
      if (lp == NULL || lp->post_landing_pad == NULL)
971
        continue;
972
 
973
      start_sequence ();
974
 
975
      lp->landing_pad = gen_label_rtx ();
976
      emit_label (lp->landing_pad);
977
      LABEL_PRESERVE_P (lp->landing_pad) = 1;
978
 
979
#ifdef HAVE_exception_receiver
980
      if (HAVE_exception_receiver)
981
        emit_insn (gen_exception_receiver ());
982
      else
983
#endif
984
#ifdef HAVE_nonlocal_goto_receiver
985
        if (HAVE_nonlocal_goto_receiver)
986
          emit_insn (gen_nonlocal_goto_receiver ());
987
        else
988
#endif
989
          { /* Nothing */ }
990
 
991
      region = lp->region;
992
      if (region->exc_ptr_reg)
993
        emit_move_insn (region->exc_ptr_reg,
994
                        gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0)));
995
      if (region->filter_reg)
996
        emit_move_insn (region->filter_reg,
997
                        gen_rtx_REG (targetm.eh_return_filter_mode (),
998
                                     EH_RETURN_DATA_REGNO (1)));
999
 
1000
      seq = get_insns ();
1001
      end_sequence ();
1002
 
1003
      bb = emit_to_new_bb_before (seq, label_rtx (lp->post_landing_pad));
1004
      e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
1005
      e->count = bb->count;
1006
      e->probability = REG_BR_PROB_BASE;
1007
    }
1008
}
1009
 
1010
 
1011
static VEC (int, heap) *sjlj_lp_call_site_index;
1012
 
1013
/* Process all active landing pads.  Assign each one a compact dispatch
1014
   index, and a call-site index.  */
1015
 
1016
static int
1017
sjlj_assign_call_site_values (void)
1018
{
1019
  htab_t ar_hash;
1020
  int i, disp_index;
1021
  eh_landing_pad lp;
1022
 
1023
  crtl->eh.action_record_data = VEC_alloc (uchar, gc, 64);
1024
  ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
1025
 
1026
  disp_index = 0;
1027
  call_site_base = 1;
1028
  for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
1029
    if (lp && lp->post_landing_pad)
1030
      {
1031
        int action, call_site;
1032
 
1033
        /* First: build the action table.  */
1034
        action = collect_one_action_chain (ar_hash, lp->region);
1035
        if (action != -1)
1036
          crtl->uses_eh_lsda = 1;
1037
 
1038
        /* Next: assign call-site values.  If dwarf2 terms, this would be
1039
           the region number assigned by convert_to_eh_region_ranges, but
1040
           handles no-action and must-not-throw differently.  */
1041
        /* Map must-not-throw to otherwise unused call-site index 0.  */
1042
        if (action == -2)
1043
          call_site = 0;
1044
        /* Map no-action to otherwise unused call-site index -1.  */
1045
        else if (action == -1)
1046
          call_site = -1;
1047
        /* Otherwise, look it up in the table.  */
1048
        else
1049
          call_site = add_call_site (GEN_INT (disp_index), action, 0);
1050
        VEC_replace (int, sjlj_lp_call_site_index, i, call_site);
1051
 
1052
        disp_index++;
1053
      }
1054
 
1055
  htab_delete (ar_hash);
1056
 
1057
  return disp_index;
1058
}
1059
 
1060
/* Emit code to record the current call-site index before every
1061
   insn that can throw.  */
1062
 
1063
static void
1064
sjlj_mark_call_sites (void)
1065
{
1066
  int last_call_site = -2;
1067
  rtx insn, mem;
1068
 
1069
  for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
1070
    {
1071
      eh_landing_pad lp;
1072
      eh_region r;
1073
      bool nothrow;
1074
      int this_call_site;
1075
      rtx before, p;
1076
 
1077
      /* Reset value tracking at extended basic block boundaries.  */
1078
      if (LABEL_P (insn))
1079
        last_call_site = -2;
1080
 
1081
      if (! INSN_P (insn))
1082
        continue;
1083
 
1084
      nothrow = get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1085
      if (nothrow)
1086
        continue;
1087
      if (lp)
1088
        this_call_site = VEC_index (int, sjlj_lp_call_site_index, lp->index);
1089
      else if (r == NULL)
1090
        {
1091
          /* Calls (and trapping insns) without notes are outside any
1092
             exception handling region in this function.  Mark them as
1093
             no action.  */
1094
          this_call_site = -1;
1095
        }
1096
      else
1097
        {
1098
          gcc_assert (r->type == ERT_MUST_NOT_THROW);
1099
          this_call_site = 0;
1100
        }
1101
 
1102
      if (this_call_site == last_call_site)
1103
        continue;
1104
 
1105
      /* Don't separate a call from it's argument loads.  */
1106
      before = insn;
1107
      if (CALL_P (insn))
1108
        before = find_first_parameter_load (insn, NULL_RTX);
1109
 
1110
      start_sequence ();
1111
      mem = adjust_address (crtl->eh.sjlj_fc, TYPE_MODE (integer_type_node),
1112
                            sjlj_fc_call_site_ofs);
1113
      emit_move_insn (mem, GEN_INT (this_call_site));
1114
      p = get_insns ();
1115
      end_sequence ();
1116
 
1117
      emit_insn_before (p, before);
1118
      last_call_site = this_call_site;
1119
    }
1120
}
1121
 
1122
/* Construct the SjLj_Function_Context.  */
1123
 
1124
static void
1125
sjlj_emit_function_enter (rtx dispatch_label)
1126
{
1127
  rtx fn_begin, fc, mem, seq;
1128
  bool fn_begin_outside_block;
1129
  rtx personality = get_personality_function (current_function_decl);
1130
 
1131
  fc = crtl->eh.sjlj_fc;
1132
 
1133
  start_sequence ();
1134
 
1135
  /* We're storing this libcall's address into memory instead of
1136
     calling it directly.  Thus, we must call assemble_external_libcall
1137
     here, as we can not depend on emit_library_call to do it for us.  */
1138
  assemble_external_libcall (personality);
1139
  mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
1140
  emit_move_insn (mem, personality);
1141
 
1142
  mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
1143
  if (crtl->uses_eh_lsda)
1144
    {
1145
      char buf[20];
1146
      rtx sym;
1147
 
1148
      ASM_GENERATE_INTERNAL_LABEL (buf, "LLSDA", current_function_funcdef_no);
1149
      sym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
1150
      SYMBOL_REF_FLAGS (sym) = SYMBOL_FLAG_LOCAL;
1151
      emit_move_insn (mem, sym);
1152
    }
1153
  else
1154
    emit_move_insn (mem, const0_rtx);
1155
 
1156
#ifdef DONT_USE_BUILTIN_SETJMP
1157
  {
1158
    rtx x, last;
1159
    x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_RETURNS_TWICE,
1160
                                 TYPE_MODE (integer_type_node), 1,
1161
                                 plus_constant (XEXP (fc, 0),
1162
                                                sjlj_fc_jbuf_ofs), Pmode);
1163
 
1164
    emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
1165
                             TYPE_MODE (integer_type_node), 0, dispatch_label);
1166
    last = get_last_insn ();
1167
    if (JUMP_P (last) && any_condjump_p (last))
1168
      {
1169
        gcc_assert (!find_reg_note (last, REG_BR_PROB, 0));
1170
        add_reg_note (last, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE / 100));
1171
      }
1172
  }
1173
#else
1174
  expand_builtin_setjmp_setup (plus_constant (XEXP (fc, 0), sjlj_fc_jbuf_ofs),
1175
                               dispatch_label);
1176
#endif
1177
 
1178
  emit_library_call (unwind_sjlj_register_libfunc, LCT_NORMAL, VOIDmode,
1179
                     1, XEXP (fc, 0), Pmode);
1180
 
1181
  seq = get_insns ();
1182
  end_sequence ();
1183
 
1184
  /* ??? Instead of doing this at the beginning of the function,
1185
     do this in a block that is at loop level 0 and dominates all
1186
     can_throw_internal instructions.  */
1187
 
1188
  fn_begin_outside_block = true;
1189
  for (fn_begin = get_insns (); ; fn_begin = NEXT_INSN (fn_begin))
1190
    if (NOTE_P (fn_begin))
1191
      {
1192
        if (NOTE_KIND (fn_begin) == NOTE_INSN_FUNCTION_BEG)
1193
          break;
1194
        else if (NOTE_INSN_BASIC_BLOCK_P (fn_begin))
1195
          fn_begin_outside_block = false;
1196
      }
1197
 
1198
  if (fn_begin_outside_block)
1199
    insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR));
1200
  else
1201
    emit_insn_after (seq, fn_begin);
1202
}
1203
 
1204
/* Call back from expand_function_end to know where we should put
1205
   the call to unwind_sjlj_unregister_libfunc if needed.  */
1206
 
1207
void
1208
sjlj_emit_function_exit_after (rtx after)
1209
{
1210
  crtl->eh.sjlj_exit_after = after;
1211
}
1212
 
1213
static void
1214
sjlj_emit_function_exit (void)
1215
{
1216
  rtx seq, insn;
1217
 
1218
  start_sequence ();
1219
 
1220
  emit_library_call (unwind_sjlj_unregister_libfunc, LCT_NORMAL, VOIDmode,
1221
                     1, XEXP (crtl->eh.sjlj_fc, 0), Pmode);
1222
 
1223
  seq = get_insns ();
1224
  end_sequence ();
1225
 
1226
  /* ??? Really this can be done in any block at loop level 0 that
1227
     post-dominates all can_throw_internal instructions.  This is
1228
     the last possible moment.  */
1229
 
1230
  insn = crtl->eh.sjlj_exit_after;
1231
  if (LABEL_P (insn))
1232
    insn = NEXT_INSN (insn);
1233
 
1234
  emit_insn_after (seq, insn);
1235
}
1236
 
1237
static void
1238
sjlj_emit_dispatch_table (rtx dispatch_label, int num_dispatch)
1239
{
1240
  enum machine_mode unwind_word_mode = targetm.unwind_word_mode ();
1241
  enum machine_mode filter_mode = targetm.eh_return_filter_mode ();
1242
  eh_landing_pad lp;
1243
  rtx mem, seq, fc, before, exc_ptr_reg, filter_reg;
1244
  rtx first_reachable_label;
1245
  basic_block bb;
1246
  eh_region r;
1247
  edge e;
1248
  int i, disp_index;
1249
  gimple switch_stmt;
1250
 
1251
  fc = crtl->eh.sjlj_fc;
1252
 
1253
  start_sequence ();
1254
 
1255
  emit_label (dispatch_label);
1256
 
1257
#ifndef DONT_USE_BUILTIN_SETJMP
1258
  expand_builtin_setjmp_receiver (dispatch_label);
1259
 
1260
  /* The caller of expand_builtin_setjmp_receiver is responsible for
1261
     making sure that the label doesn't vanish.  The only other caller
1262
     is the expander for __builtin_setjmp_receiver, which places this
1263
     label on the nonlocal_goto_label list.  Since we're modeling these
1264
     CFG edges more exactly, we can use the forced_labels list instead.  */
1265
  LABEL_PRESERVE_P (dispatch_label) = 1;
1266
  forced_labels
1267
    = gen_rtx_EXPR_LIST (VOIDmode, dispatch_label, forced_labels);
1268
#endif
1269
 
1270
  /* Load up exc_ptr and filter values from the function context.  */
1271
  mem = adjust_address (fc, unwind_word_mode, sjlj_fc_data_ofs);
1272
  if (unwind_word_mode != ptr_mode)
1273
    {
1274
#ifdef POINTERS_EXTEND_UNSIGNED
1275
      mem = convert_memory_address (ptr_mode, mem);
1276
#else
1277
      mem = convert_to_mode (ptr_mode, mem, 0);
1278
#endif
1279
    }
1280
  exc_ptr_reg = force_reg (ptr_mode, mem);
1281
 
1282
  mem = adjust_address (fc, unwind_word_mode,
1283
                        sjlj_fc_data_ofs + GET_MODE_SIZE (unwind_word_mode));
1284
  if (unwind_word_mode != filter_mode)
1285
    mem = convert_to_mode (filter_mode, mem, 0);
1286
  filter_reg = force_reg (filter_mode, mem);
1287
 
1288
  /* Jump to one of the directly reachable regions.  */
1289
 
1290
  disp_index = 0;
1291
  first_reachable_label = NULL;
1292
 
1293
  /* If there's exactly one call site in the function, don't bother
1294
     generating a switch statement.  */
1295
  switch_stmt = NULL;
1296
  if (num_dispatch > 1)
1297
    {
1298
      tree disp;
1299
 
1300
      mem = adjust_address (fc, TYPE_MODE (integer_type_node),
1301
                            sjlj_fc_call_site_ofs);
1302
      disp = make_tree (integer_type_node, mem);
1303
 
1304
      switch_stmt = gimple_build_switch_nlabels (num_dispatch, disp, NULL);
1305
    }
1306
 
1307
  for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
1308
    if (lp && lp->post_landing_pad)
1309
      {
1310
        rtx seq2, label;
1311
 
1312
        start_sequence ();
1313
 
1314
        lp->landing_pad = dispatch_label;
1315
 
1316
        if (num_dispatch > 1)
1317
          {
1318
            tree t_label, case_elt;
1319
 
1320
            t_label = create_artificial_label (UNKNOWN_LOCATION);
1321
            case_elt = build3 (CASE_LABEL_EXPR, void_type_node,
1322
                               build_int_cst (NULL, disp_index),
1323
                               NULL, t_label);
1324
            gimple_switch_set_label (switch_stmt, disp_index, case_elt);
1325
 
1326
            label = label_rtx (t_label);
1327
          }
1328
        else
1329
          label = gen_label_rtx ();
1330
 
1331
        if (disp_index == 0)
1332
          first_reachable_label = label;
1333
        emit_label (label);
1334
 
1335
        r = lp->region;
1336
        if (r->exc_ptr_reg)
1337
          emit_move_insn (r->exc_ptr_reg, exc_ptr_reg);
1338
        if (r->filter_reg)
1339
          emit_move_insn (r->filter_reg, filter_reg);
1340
 
1341
        seq2 = get_insns ();
1342
        end_sequence ();
1343
 
1344
        before = label_rtx (lp->post_landing_pad);
1345
        bb = emit_to_new_bb_before (seq2, before);
1346
        e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
1347
        e->count = bb->count;
1348
        e->probability = REG_BR_PROB_BASE;
1349
 
1350
        disp_index++;
1351
      }
1352
  gcc_assert (disp_index == num_dispatch);
1353
 
1354
  if (num_dispatch > 1)
1355
    {
1356
      expand_case (switch_stmt);
1357
      expand_builtin_trap ();
1358
    }
1359
 
1360
  seq = get_insns ();
1361
  end_sequence ();
1362
 
1363
  bb = emit_to_new_bb_before (seq, first_reachable_label);
1364
  if (num_dispatch == 1)
1365
    {
1366
      e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
1367
      e->count = bb->count;
1368
      e->probability = REG_BR_PROB_BASE;
1369
    }
1370
}
1371
 
1372
static void
1373
sjlj_build_landing_pads (void)
1374
{
1375
  int num_dispatch;
1376
 
1377
  num_dispatch = VEC_length (eh_landing_pad, cfun->eh->lp_array);
1378
  if (num_dispatch == 0)
1379
    return;
1380
  VEC_safe_grow (int, heap, sjlj_lp_call_site_index, num_dispatch);
1381
 
1382
  num_dispatch = sjlj_assign_call_site_values ();
1383
  if (num_dispatch > 0)
1384
    {
1385
      rtx dispatch_label = gen_label_rtx ();
1386
      int align = STACK_SLOT_ALIGNMENT (sjlj_fc_type_node,
1387
                                        TYPE_MODE (sjlj_fc_type_node),
1388
                                        TYPE_ALIGN (sjlj_fc_type_node));
1389
      crtl->eh.sjlj_fc
1390
        = assign_stack_local (TYPE_MODE (sjlj_fc_type_node),
1391
                              int_size_in_bytes (sjlj_fc_type_node),
1392
                              align);
1393
 
1394
      sjlj_mark_call_sites ();
1395
      sjlj_emit_function_enter (dispatch_label);
1396
      sjlj_emit_dispatch_table (dispatch_label, num_dispatch);
1397
      sjlj_emit_function_exit ();
1398
    }
1399
 
1400
  VEC_free (int, heap, sjlj_lp_call_site_index);
1401
}
1402
 
1403
/* After initial rtl generation, call back to finish generating
1404
   exception support code.  */
1405
 
1406
static void
1407
finish_eh_generation (void)
1408
{
1409
  basic_block bb;
1410
 
1411
  /* Construct the landing pads.  */
1412
  if (USING_SJLJ_EXCEPTIONS)
1413
    sjlj_build_landing_pads ();
1414
  else
1415
    dw2_build_landing_pads ();
1416
  break_superblocks ();
1417
 
1418
  if (USING_SJLJ_EXCEPTIONS
1419
      /* Kludge for Alpha/Tru64 (see alpha_gp_save_rtx).  */
1420
      || single_succ_edge (ENTRY_BLOCK_PTR)->insns.r)
1421
    commit_edge_insertions ();
1422
 
1423
  /* Redirect all EH edges from the post_landing_pad to the landing pad.  */
1424
  FOR_EACH_BB (bb)
1425
    {
1426
      eh_landing_pad lp;
1427
      edge_iterator ei;
1428
      edge e;
1429
 
1430
      lp = get_eh_landing_pad_from_rtx (BB_END (bb));
1431
 
1432
      FOR_EACH_EDGE (e, ei, bb->succs)
1433
        if (e->flags & EDGE_EH)
1434
          break;
1435
 
1436
      /* We should not have generated any new throwing insns during this
1437
         pass, and we should not have lost any EH edges, so we only need
1438
         to handle two cases here:
1439
         (1) reachable handler and an existing edge to post-landing-pad,
1440
         (2) no reachable handler and no edge.  */
1441
      gcc_assert ((lp != NULL) == (e != NULL));
1442
      if (lp != NULL)
1443
        {
1444
          gcc_assert (BB_HEAD (e->dest) == label_rtx (lp->post_landing_pad));
1445
 
1446
          redirect_edge_succ (e, BLOCK_FOR_INSN (lp->landing_pad));
1447
          e->flags |= (CALL_P (BB_END (bb))
1448
                       ? EDGE_ABNORMAL | EDGE_ABNORMAL_CALL
1449
                       : EDGE_ABNORMAL);
1450
        }
1451
    }
1452
}
1453
 
1454
static bool
1455
gate_handle_eh (void)
1456
{
1457
  /* Nothing to do if no regions created.  */
1458
  return cfun->eh->region_tree != NULL;
1459
}
1460
 
1461
/* Complete generation of exception handling code.  */
1462
static unsigned int
1463
rest_of_handle_eh (void)
1464
{
1465
  finish_eh_generation ();
1466
  cleanup_cfg (CLEANUP_NO_INSN_DEL);
1467
  return 0;
1468
}
1469
 
1470
struct rtl_opt_pass pass_rtl_eh =
1471
{
1472
 {
1473
  RTL_PASS,
1474
  "rtl eh",                             /* name */
1475
  gate_handle_eh,                       /* gate */
1476
  rest_of_handle_eh,                    /* execute */
1477
  NULL,                                 /* sub */
1478
  NULL,                                 /* next */
1479
  0,                                    /* static_pass_number */
1480
  TV_JUMP,                              /* tv_id */
1481
  0,                                    /* properties_required */
1482
  0,                                    /* properties_provided */
1483
  0,                                    /* properties_destroyed */
1484
  0,                                    /* todo_flags_start */
1485
  TODO_dump_func                        /* todo_flags_finish */
1486
 }
1487
};
1488
 
1489
/* This section handles removing dead code for flow.  */
1490
 
1491
void
1492
remove_eh_landing_pad (eh_landing_pad lp)
1493
{
1494
  eh_landing_pad *pp;
1495
 
1496
  for (pp = &lp->region->landing_pads; *pp != lp; pp = &(*pp)->next_lp)
1497
    continue;
1498
  *pp = lp->next_lp;
1499
 
1500
  if (lp->post_landing_pad)
1501
    EH_LANDING_PAD_NR (lp->post_landing_pad) = 0;
1502
  VEC_replace (eh_landing_pad, cfun->eh->lp_array, lp->index, NULL);
1503
}
1504
 
1505
/* Splice REGION from the region tree.  */
1506
 
1507
void
1508
remove_eh_handler (eh_region region)
1509
{
1510
  eh_region *pp, *pp_start, p, outer;
1511
  eh_landing_pad lp;
1512
 
1513
  for (lp = region->landing_pads; lp ; lp = lp->next_lp)
1514
    {
1515
      if (lp->post_landing_pad)
1516
        EH_LANDING_PAD_NR (lp->post_landing_pad) = 0;
1517
      VEC_replace (eh_landing_pad, cfun->eh->lp_array, lp->index, NULL);
1518
    }
1519
 
1520
  outer = region->outer;
1521
  if (outer)
1522
    pp_start = &outer->inner;
1523
  else
1524
    pp_start = &cfun->eh->region_tree;
1525
  for (pp = pp_start, p = *pp; p != region; pp = &p->next_peer, p = *pp)
1526
    continue;
1527
  if (region->inner)
1528
    {
1529
      *pp = p = region->inner;
1530
      do
1531
        {
1532
          p->outer = outer;
1533
          pp = &p->next_peer;
1534
          p = *pp;
1535
        }
1536
      while (p);
1537
    }
1538
  *pp = region->next_peer;
1539
 
1540
  VEC_replace (eh_region, cfun->eh->region_array, region->index, NULL);
1541
}
1542
 
1543
/* Invokes CALLBACK for every exception handler landing pad label.
1544
   Only used by reload hackery; should not be used by new code.  */
1545
 
1546
void
1547
for_each_eh_label (void (*callback) (rtx))
1548
{
1549
  eh_landing_pad lp;
1550
  int i;
1551
 
1552
  for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
1553
    {
1554
      if (lp)
1555
        {
1556
          rtx lab = lp->landing_pad;
1557
          if (lab && LABEL_P (lab))
1558
            (*callback) (lab);
1559
        }
1560
    }
1561
}
1562
 
1563
/* Create the REG_EH_REGION note for INSN, given its ECF_FLAGS for a
1564
   call insn.
1565
 
1566
   At the gimple level, we use LP_NR
1567
       > 0 : The statement transfers to landing pad LP_NR
1568
       = 0 : The statement is outside any EH region
1569
       < 0 : The statement is within MUST_NOT_THROW region -LP_NR.
1570
 
1571
   At the rtl level, we use LP_NR
1572
       > 0 : The insn transfers to landing pad LP_NR
1573
       = 0 : The insn cannot throw
1574
       < 0 : The insn is within MUST_NOT_THROW region -LP_NR
1575
       = INT_MIN : The insn cannot throw or execute a nonlocal-goto.
1576
       missing note: The insn is outside any EH region.
1577
 
1578
  ??? This difference probably ought to be avoided.  We could stand
1579
  to record nothrow for arbitrary gimple statements, and so avoid
1580
  some moderately complex lookups in stmt_could_throw_p.  Perhaps
1581
  NOTHROW should be mapped on both sides to INT_MIN.  Perhaps the
1582
  no-nonlocal-goto property should be recorded elsewhere as a bit
1583
  on the call_insn directly.  Perhaps we should make more use of
1584
  attaching the trees to call_insns (reachable via symbol_ref in
1585
  direct call cases) and just pull the data out of the trees.  */
1586
 
1587
void
1588
make_reg_eh_region_note (rtx insn, int ecf_flags, int lp_nr)
1589
{
1590
  rtx value;
1591
  if (ecf_flags & ECF_NOTHROW)
1592
    value = const0_rtx;
1593
  else if (lp_nr != 0)
1594
    value = GEN_INT (lp_nr);
1595
  else
1596
    return;
1597
  add_reg_note (insn, REG_EH_REGION, value);
1598
}
1599
 
1600
/* Create a REG_EH_REGION note for a CALL_INSN that cannot throw
1601
   nor perform a non-local goto.  Replace the region note if it
1602
   already exists.  */
1603
 
1604
void
1605
make_reg_eh_region_note_nothrow_nononlocal (rtx insn)
1606
{
1607
  rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1608
  rtx intmin = GEN_INT (INT_MIN);
1609
 
1610
  if (note != 0)
1611
    XEXP (note, 0) = intmin;
1612
  else
1613
    add_reg_note (insn, REG_EH_REGION, intmin);
1614
}
1615
 
1616
/* Return true if INSN could throw, assuming no REG_EH_REGION note
1617
   to the contrary.  */
1618
 
1619
bool
1620
insn_could_throw_p (const_rtx insn)
1621
{
1622
  if (!flag_exceptions)
1623
    return false;
1624
  if (CALL_P (insn))
1625
    return true;
1626
  if (INSN_P (insn) && flag_non_call_exceptions)
1627
    return may_trap_p (PATTERN (insn));
1628
  return false;
1629
}
1630
 
1631
/* Copy an REG_EH_REGION note to each insn that might throw beginning
1632
   at FIRST and ending at LAST.  NOTE_OR_INSN is either the source insn
1633
   to look for a note, or the note itself.  */
1634
 
1635
void
1636
copy_reg_eh_region_note_forward (rtx note_or_insn, rtx first, rtx last)
1637
{
1638
  rtx insn, note = note_or_insn;
1639
 
1640
  if (INSN_P (note_or_insn))
1641
    {
1642
      note = find_reg_note (note_or_insn, REG_EH_REGION, NULL_RTX);
1643
      if (note == NULL)
1644
        return;
1645
    }
1646
  note = XEXP (note, 0);
1647
 
1648
  for (insn = first; insn != last ; insn = NEXT_INSN (insn))
1649
    if (!find_reg_note (insn, REG_EH_REGION, NULL_RTX)
1650
        && insn_could_throw_p (insn))
1651
      add_reg_note (insn, REG_EH_REGION, note);
1652
}
1653
 
1654
/* Likewise, but iterate backward.  */
1655
 
1656
void
1657
copy_reg_eh_region_note_backward (rtx note_or_insn, rtx last, rtx first)
1658
{
1659
  rtx insn, note = note_or_insn;
1660
 
1661
  if (INSN_P (note_or_insn))
1662
    {
1663
      note = find_reg_note (note_or_insn, REG_EH_REGION, NULL_RTX);
1664
      if (note == NULL)
1665
        return;
1666
    }
1667
  note = XEXP (note, 0);
1668
 
1669
  for (insn = last; insn != first; insn = PREV_INSN (insn))
1670
    if (insn_could_throw_p (insn))
1671
      add_reg_note (insn, REG_EH_REGION, note);
1672
}
1673
 
1674
 
1675
/* Extract all EH information from INSN.  Return true if the insn
1676
   was marked NOTHROW.  */
1677
 
1678
static bool
1679
get_eh_region_and_lp_from_rtx (const_rtx insn, eh_region *pr,
1680
                               eh_landing_pad *plp)
1681
{
1682
  eh_landing_pad lp = NULL;
1683
  eh_region r = NULL;
1684
  bool ret = false;
1685
  rtx note;
1686
  int lp_nr;
1687
 
1688
  if (! INSN_P (insn))
1689
    goto egress;
1690
 
1691
  if (NONJUMP_INSN_P (insn)
1692
      && GET_CODE (PATTERN (insn)) == SEQUENCE)
1693
    insn = XVECEXP (PATTERN (insn), 0, 0);
1694
 
1695
  note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1696
  if (!note)
1697
    {
1698
      ret = !insn_could_throw_p (insn);
1699
      goto egress;
1700
    }
1701
 
1702
  lp_nr = INTVAL (XEXP (note, 0));
1703
  if (lp_nr == 0 || lp_nr == INT_MIN)
1704
    {
1705
      ret = true;
1706
      goto egress;
1707
    }
1708
 
1709
  if (lp_nr < 0)
1710
    r = VEC_index (eh_region, cfun->eh->region_array, -lp_nr);
1711
  else
1712
    {
1713
      lp = VEC_index (eh_landing_pad, cfun->eh->lp_array, lp_nr);
1714
      r = lp->region;
1715
    }
1716
 
1717
 egress:
1718
  *plp = lp;
1719
  *pr = r;
1720
  return ret;
1721
}
1722
 
1723
/* Return the landing pad to which INSN may go, or NULL if it does not
1724
   have a reachable landing pad within this function.  */
1725
 
1726
eh_landing_pad
1727
get_eh_landing_pad_from_rtx (const_rtx insn)
1728
{
1729
  eh_landing_pad lp;
1730
  eh_region r;
1731
 
1732
  get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1733
  return lp;
1734
}
1735
 
1736
/* Return the region to which INSN may go, or NULL if it does not
1737
   have a reachable region within this function.  */
1738
 
1739
eh_region
1740
get_eh_region_from_rtx (const_rtx insn)
1741
{
1742
  eh_landing_pad lp;
1743
  eh_region r;
1744
 
1745
  get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1746
  return r;
1747
}
1748
 
1749
/* Return true if INSN throws and is caught by something in this function.  */
1750
 
1751
bool
1752
can_throw_internal (const_rtx insn)
1753
{
1754
  return get_eh_landing_pad_from_rtx (insn) != NULL;
1755
}
1756
 
1757
/* Return true if INSN throws and escapes from the current function.  */
1758
 
1759
bool
1760
can_throw_external (const_rtx insn)
1761
{
1762
  eh_landing_pad lp;
1763
  eh_region r;
1764
  bool nothrow;
1765
 
1766
  if (! INSN_P (insn))
1767
    return false;
1768
 
1769
  if (NONJUMP_INSN_P (insn)
1770
      && GET_CODE (PATTERN (insn)) == SEQUENCE)
1771
    {
1772
      rtx seq = PATTERN (insn);
1773
      int i, n = XVECLEN (seq, 0);
1774
 
1775
      for (i = 0; i < n; i++)
1776
        if (can_throw_external (XVECEXP (seq, 0, i)))
1777
          return true;
1778
 
1779
      return false;
1780
    }
1781
 
1782
  nothrow = get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1783
 
1784
  /* If we can't throw, we obviously can't throw external.  */
1785
  if (nothrow)
1786
    return false;
1787
 
1788
  /* If we have an internal landing pad, then we're not external.  */
1789
  if (lp != NULL)
1790
    return false;
1791
 
1792
  /* If we're not within an EH region, then we are external.  */
1793
  if (r == NULL)
1794
    return true;
1795
 
1796
  /* The only thing that ought to be left is MUST_NOT_THROW regions,
1797
     which don't always have landing pads.  */
1798
  gcc_assert (r->type == ERT_MUST_NOT_THROW);
1799
  return false;
1800
}
1801
 
1802
/* Return true if INSN cannot throw at all.  */
1803
 
1804
bool
1805
insn_nothrow_p (const_rtx insn)
1806
{
1807
  eh_landing_pad lp;
1808
  eh_region r;
1809
 
1810
  if (! INSN_P (insn))
1811
    return true;
1812
 
1813
  if (NONJUMP_INSN_P (insn)
1814
      && GET_CODE (PATTERN (insn)) == SEQUENCE)
1815
    {
1816
      rtx seq = PATTERN (insn);
1817
      int i, n = XVECLEN (seq, 0);
1818
 
1819
      for (i = 0; i < n; i++)
1820
        if (!insn_nothrow_p (XVECEXP (seq, 0, i)))
1821
          return false;
1822
 
1823
      return true;
1824
    }
1825
 
1826
  return get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1827
}
1828
 
1829
/* Return true if INSN can perform a non-local goto.  */
1830
/* ??? This test is here in this file because it (ab)uses REG_EH_REGION.  */
1831
 
1832
bool
1833
can_nonlocal_goto (const_rtx insn)
1834
{
1835
  if (nonlocal_goto_handler_labels && CALL_P (insn))
1836
    {
1837
      rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1838
      if (!note || INTVAL (XEXP (note, 0)) != INT_MIN)
1839
        return true;
1840
    }
1841
  return false;
1842
}
1843
 
1844
/* Set TREE_NOTHROW and crtl->all_throwers_are_sibcalls.  */
1845
 
1846
static unsigned int
1847
set_nothrow_function_flags (void)
1848
{
1849
  rtx insn;
1850
 
1851
  crtl->nothrow = 1;
1852
 
1853
  /* Assume crtl->all_throwers_are_sibcalls until we encounter
1854
     something that can throw an exception.  We specifically exempt
1855
     CALL_INSNs that are SIBLING_CALL_P, as these are really jumps,
1856
     and can't throw.  Most CALL_INSNs are not SIBLING_CALL_P, so this
1857
     is optimistic.  */
1858
 
1859
  crtl->all_throwers_are_sibcalls = 1;
1860
 
1861
  /* If we don't know that this implementation of the function will
1862
     actually be used, then we must not set TREE_NOTHROW, since
1863
     callers must not assume that this function does not throw.  */
1864
  if (TREE_NOTHROW (current_function_decl))
1865
    return 0;
1866
 
1867
  if (! flag_exceptions)
1868
    return 0;
1869
 
1870
  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
1871
    if (can_throw_external (insn))
1872
      {
1873
        crtl->nothrow = 0;
1874
 
1875
        if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
1876
          {
1877
            crtl->all_throwers_are_sibcalls = 0;
1878
            return 0;
1879
          }
1880
      }
1881
 
1882
  for (insn = crtl->epilogue_delay_list; insn;
1883
       insn = XEXP (insn, 1))
1884
    if (can_throw_external (insn))
1885
      {
1886
        crtl->nothrow = 0;
1887
 
1888
        if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
1889
          {
1890
            crtl->all_throwers_are_sibcalls = 0;
1891
            return 0;
1892
          }
1893
      }
1894
  if (crtl->nothrow
1895
      && (cgraph_function_body_availability (cgraph_node
1896
                                             (current_function_decl))
1897
          >= AVAIL_AVAILABLE))
1898
    {
1899
      struct cgraph_node *node = cgraph_node (current_function_decl);
1900
      struct cgraph_edge *e;
1901
      for (e = node->callers; e; e = e->next_caller)
1902
        e->can_throw_external = false;
1903
      cgraph_set_nothrow_flag (node, true);
1904
 
1905
      if (dump_file)
1906
        fprintf (dump_file, "Marking function nothrow: %s\n\n",
1907
                 current_function_name ());
1908
    }
1909
  return 0;
1910
}
1911
 
1912
struct rtl_opt_pass pass_set_nothrow_function_flags =
1913
{
1914
 {
1915
  RTL_PASS,
1916
  "nothrow",                            /* name */
1917
  NULL,                                 /* gate */
1918
  set_nothrow_function_flags,           /* execute */
1919
  NULL,                                 /* sub */
1920
  NULL,                                 /* next */
1921
  0,                                    /* static_pass_number */
1922
  TV_NONE,                              /* tv_id */
1923
  0,                                    /* properties_required */
1924
  0,                                    /* properties_provided */
1925
  0,                                    /* properties_destroyed */
1926
  0,                                    /* todo_flags_start */
1927
  TODO_dump_func,                       /* todo_flags_finish */
1928
 }
1929
};
1930
 
1931
 
1932
/* Various hooks for unwind library.  */
1933
 
1934
/* Expand the EH support builtin functions:
1935
   __builtin_eh_pointer and __builtin_eh_filter.  */
1936
 
1937
static eh_region
1938
expand_builtin_eh_common (tree region_nr_t)
1939
{
1940
  HOST_WIDE_INT region_nr;
1941
  eh_region region;
1942
 
1943
  gcc_assert (host_integerp (region_nr_t, 0));
1944
  region_nr = tree_low_cst (region_nr_t, 0);
1945
 
1946
  region = VEC_index (eh_region, cfun->eh->region_array, region_nr);
1947
 
1948
  /* ??? We shouldn't have been able to delete a eh region without
1949
     deleting all the code that depended on it.  */
1950
  gcc_assert (region != NULL);
1951
 
1952
  return region;
1953
}
1954
 
1955
/* Expand to the exc_ptr value from the given eh region.  */
1956
 
1957
rtx
1958
expand_builtin_eh_pointer (tree exp)
1959
{
1960
  eh_region region
1961
    = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0));
1962
  if (region->exc_ptr_reg == NULL)
1963
    region->exc_ptr_reg = gen_reg_rtx (ptr_mode);
1964
  return region->exc_ptr_reg;
1965
}
1966
 
1967
/* Expand to the filter value from the given eh region.  */
1968
 
1969
rtx
1970
expand_builtin_eh_filter (tree exp)
1971
{
1972
  eh_region region
1973
    = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0));
1974
  if (region->filter_reg == NULL)
1975
    region->filter_reg = gen_reg_rtx (targetm.eh_return_filter_mode ());
1976
  return region->filter_reg;
1977
}
1978
 
1979
/* Copy the exc_ptr and filter values from one landing pad's registers
1980
   to another.  This is used to inline the resx statement.  */
1981
 
1982
rtx
1983
expand_builtin_eh_copy_values (tree exp)
1984
{
1985
  eh_region dst
1986
    = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0));
1987
  eh_region src
1988
    = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 1));
1989
  enum machine_mode fmode = targetm.eh_return_filter_mode ();
1990
 
1991
  if (dst->exc_ptr_reg == NULL)
1992
    dst->exc_ptr_reg = gen_reg_rtx (ptr_mode);
1993
  if (src->exc_ptr_reg == NULL)
1994
    src->exc_ptr_reg = gen_reg_rtx (ptr_mode);
1995
 
1996
  if (dst->filter_reg == NULL)
1997
    dst->filter_reg = gen_reg_rtx (fmode);
1998
  if (src->filter_reg == NULL)
1999
    src->filter_reg = gen_reg_rtx (fmode);
2000
 
2001
  emit_move_insn (dst->exc_ptr_reg, src->exc_ptr_reg);
2002
  emit_move_insn (dst->filter_reg, src->filter_reg);
2003
 
2004
  return const0_rtx;
2005
}
2006
 
2007
/* Do any necessary initialization to access arbitrary stack frames.
2008
   On the SPARC, this means flushing the register windows.  */
2009
 
2010
void
2011
expand_builtin_unwind_init (void)
2012
{
2013
  /* Set this so all the registers get saved in our frame; we need to be
2014
     able to copy the saved values for any registers from frames we unwind.  */
2015
  crtl->saves_all_registers = 1;
2016
 
2017
#ifdef SETUP_FRAME_ADDRESSES
2018
  SETUP_FRAME_ADDRESSES ();
2019
#endif
2020
}
2021
 
2022
/* Map a non-negative number to an eh return data register number; expands
2023
   to -1 if no return data register is associated with the input number.
2024
   At least the inputs 0 and 1 must be mapped; the target may provide more.  */
2025
 
2026
rtx
2027
expand_builtin_eh_return_data_regno (tree exp)
2028
{
2029
  tree which = CALL_EXPR_ARG (exp, 0);
2030
  unsigned HOST_WIDE_INT iwhich;
2031
 
2032
  if (TREE_CODE (which) != INTEGER_CST)
2033
    {
2034
      error ("argument of %<__builtin_eh_return_regno%> must be constant");
2035
      return constm1_rtx;
2036
    }
2037
 
2038
  iwhich = tree_low_cst (which, 1);
2039
  iwhich = EH_RETURN_DATA_REGNO (iwhich);
2040
  if (iwhich == INVALID_REGNUM)
2041
    return constm1_rtx;
2042
 
2043
#ifdef DWARF_FRAME_REGNUM
2044
  iwhich = DWARF_FRAME_REGNUM (iwhich);
2045
#else
2046
  iwhich = DBX_REGISTER_NUMBER (iwhich);
2047
#endif
2048
 
2049
  return GEN_INT (iwhich);
2050
}
2051
 
2052
/* Given a value extracted from the return address register or stack slot,
2053
   return the actual address encoded in that value.  */
2054
 
2055
rtx
2056
expand_builtin_extract_return_addr (tree addr_tree)
2057
{
2058
  rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
2059
 
2060
  if (GET_MODE (addr) != Pmode
2061
      && GET_MODE (addr) != VOIDmode)
2062
    {
2063
#ifdef POINTERS_EXTEND_UNSIGNED
2064
      addr = convert_memory_address (Pmode, addr);
2065
#else
2066
      addr = convert_to_mode (Pmode, addr, 0);
2067
#endif
2068
    }
2069
 
2070
  /* First mask out any unwanted bits.  */
2071
#ifdef MASK_RETURN_ADDR
2072
  expand_and (Pmode, addr, MASK_RETURN_ADDR, addr);
2073
#endif
2074
 
2075
  /* Then adjust to find the real return address.  */
2076
#if defined (RETURN_ADDR_OFFSET)
2077
  addr = plus_constant (addr, RETURN_ADDR_OFFSET);
2078
#endif
2079
 
2080
  return addr;
2081
}
2082
 
2083
/* Given an actual address in addr_tree, do any necessary encoding
2084
   and return the value to be stored in the return address register or
2085
   stack slot so the epilogue will return to that address.  */
2086
 
2087
rtx
2088
expand_builtin_frob_return_addr (tree addr_tree)
2089
{
2090
  rtx addr = expand_expr (addr_tree, NULL_RTX, ptr_mode, EXPAND_NORMAL);
2091
 
2092
  addr = convert_memory_address (Pmode, addr);
2093
 
2094
#ifdef RETURN_ADDR_OFFSET
2095
  addr = force_reg (Pmode, addr);
2096
  addr = plus_constant (addr, -RETURN_ADDR_OFFSET);
2097
#endif
2098
 
2099
  return addr;
2100
}
2101
 
2102
/* Set up the epilogue with the magic bits we'll need to return to the
2103
   exception handler.  */
2104
 
2105
void
2106
expand_builtin_eh_return (tree stackadj_tree ATTRIBUTE_UNUSED,
2107
                          tree handler_tree)
2108
{
2109
  rtx tmp;
2110
 
2111
#ifdef EH_RETURN_STACKADJ_RTX
2112
  tmp = expand_expr (stackadj_tree, crtl->eh.ehr_stackadj,
2113
                     VOIDmode, EXPAND_NORMAL);
2114
  tmp = convert_memory_address (Pmode, tmp);
2115
  if (!crtl->eh.ehr_stackadj)
2116
    crtl->eh.ehr_stackadj = copy_to_reg (tmp);
2117
  else if (tmp != crtl->eh.ehr_stackadj)
2118
    emit_move_insn (crtl->eh.ehr_stackadj, tmp);
2119
#endif
2120
 
2121
  tmp = expand_expr (handler_tree, crtl->eh.ehr_handler,
2122
                     VOIDmode, EXPAND_NORMAL);
2123
  tmp = convert_memory_address (Pmode, tmp);
2124
  if (!crtl->eh.ehr_handler)
2125
    crtl->eh.ehr_handler = copy_to_reg (tmp);
2126
  else if (tmp != crtl->eh.ehr_handler)
2127
    emit_move_insn (crtl->eh.ehr_handler, tmp);
2128
 
2129
  if (!crtl->eh.ehr_label)
2130
    crtl->eh.ehr_label = gen_label_rtx ();
2131
  emit_jump (crtl->eh.ehr_label);
2132
}
2133
 
2134
/* Expand __builtin_eh_return.  This exit path from the function loads up
2135
   the eh return data registers, adjusts the stack, and branches to a
2136
   given PC other than the normal return address.  */
2137
 
2138
void
2139
expand_eh_return (void)
2140
{
2141
  rtx around_label;
2142
 
2143
  if (! crtl->eh.ehr_label)
2144
    return;
2145
 
2146
  crtl->calls_eh_return = 1;
2147
 
2148
#ifdef EH_RETURN_STACKADJ_RTX
2149
  emit_move_insn (EH_RETURN_STACKADJ_RTX, const0_rtx);
2150
#endif
2151
 
2152
  around_label = gen_label_rtx ();
2153
  emit_jump (around_label);
2154
 
2155
  emit_label (crtl->eh.ehr_label);
2156
  clobber_return_register ();
2157
 
2158
#ifdef EH_RETURN_STACKADJ_RTX
2159
  emit_move_insn (EH_RETURN_STACKADJ_RTX, crtl->eh.ehr_stackadj);
2160
#endif
2161
 
2162
#ifdef HAVE_eh_return
2163
  if (HAVE_eh_return)
2164
    emit_insn (gen_eh_return (crtl->eh.ehr_handler));
2165
  else
2166
#endif
2167
    {
2168
#ifdef EH_RETURN_HANDLER_RTX
2169
      emit_move_insn (EH_RETURN_HANDLER_RTX, crtl->eh.ehr_handler);
2170
#else
2171
      error ("__builtin_eh_return not supported on this target");
2172
#endif
2173
    }
2174
 
2175
  emit_label (around_label);
2176
}
2177
 
2178
/* Convert a ptr_mode address ADDR_TREE to a Pmode address controlled by
2179
   POINTERS_EXTEND_UNSIGNED and return it.  */
2180
 
2181
rtx
2182
expand_builtin_extend_pointer (tree addr_tree)
2183
{
2184
  rtx addr = expand_expr (addr_tree, NULL_RTX, ptr_mode, EXPAND_NORMAL);
2185
  int extend;
2186
 
2187
#ifdef POINTERS_EXTEND_UNSIGNED
2188
  extend = POINTERS_EXTEND_UNSIGNED;
2189
#else
2190
  /* The previous EH code did an unsigned extend by default, so we do this also
2191
     for consistency.  */
2192
  extend = 1;
2193
#endif
2194
 
2195
  return convert_modes (targetm.unwind_word_mode (), ptr_mode, addr, extend);
2196
}
2197
 
2198
/* In the following functions, we represent entries in the action table
2199
   as 1-based indices.  Special cases are:
2200
 
2201
         0:     null action record, non-null landing pad; implies cleanups
2202
        -1:     null action record, null landing pad; implies no action
2203
        -2:     no call-site entry; implies must_not_throw
2204
        -3:     we have yet to process outer regions
2205
 
2206
   Further, no special cases apply to the "next" field of the record.
2207
   For next, 0 means end of list.  */
2208
 
2209
struct action_record
2210
{
2211
  int offset;
2212
  int filter;
2213
  int next;
2214
};
2215
 
2216
static int
2217
action_record_eq (const void *pentry, const void *pdata)
2218
{
2219
  const struct action_record *entry = (const struct action_record *) pentry;
2220
  const struct action_record *data = (const struct action_record *) pdata;
2221
  return entry->filter == data->filter && entry->next == data->next;
2222
}
2223
 
2224
static hashval_t
2225
action_record_hash (const void *pentry)
2226
{
2227
  const struct action_record *entry = (const struct action_record *) pentry;
2228
  return entry->next * 1009 + entry->filter;
2229
}
2230
 
2231
static int
2232
add_action_record (htab_t ar_hash, int filter, int next)
2233
{
2234
  struct action_record **slot, *new_ar, tmp;
2235
 
2236
  tmp.filter = filter;
2237
  tmp.next = next;
2238
  slot = (struct action_record **) htab_find_slot (ar_hash, &tmp, INSERT);
2239
 
2240
  if ((new_ar = *slot) == NULL)
2241
    {
2242
      new_ar = XNEW (struct action_record);
2243
      new_ar->offset = VEC_length (uchar, crtl->eh.action_record_data) + 1;
2244
      new_ar->filter = filter;
2245
      new_ar->next = next;
2246
      *slot = new_ar;
2247
 
2248
      /* The filter value goes in untouched.  The link to the next
2249
         record is a "self-relative" byte offset, or zero to indicate
2250
         that there is no next record.  So convert the absolute 1 based
2251
         indices we've been carrying around into a displacement.  */
2252
 
2253
      push_sleb128 (&crtl->eh.action_record_data, filter);
2254
      if (next)
2255
        next -= VEC_length (uchar, crtl->eh.action_record_data) + 1;
2256
      push_sleb128 (&crtl->eh.action_record_data, next);
2257
    }
2258
 
2259
  return new_ar->offset;
2260
}
2261
 
2262
static int
2263
collect_one_action_chain (htab_t ar_hash, eh_region region)
2264
{
2265
  int next;
2266
 
2267
  /* If we've reached the top of the region chain, then we have
2268
     no actions, and require no landing pad.  */
2269
  if (region == NULL)
2270
    return -1;
2271
 
2272
  switch (region->type)
2273
    {
2274
    case ERT_CLEANUP:
2275
      {
2276
        eh_region r;
2277
        /* A cleanup adds a zero filter to the beginning of the chain, but
2278
           there are special cases to look out for.  If there are *only*
2279
           cleanups along a path, then it compresses to a zero action.
2280
           Further, if there are multiple cleanups along a path, we only
2281
           need to represent one of them, as that is enough to trigger
2282
           entry to the landing pad at runtime.  */
2283
        next = collect_one_action_chain (ar_hash, region->outer);
2284
        if (next <= 0)
2285
          return 0;
2286
        for (r = region->outer; r ; r = r->outer)
2287
          if (r->type == ERT_CLEANUP)
2288
            return next;
2289
        return add_action_record (ar_hash, 0, next);
2290
      }
2291
 
2292
    case ERT_TRY:
2293
      {
2294
        eh_catch c;
2295
 
2296
        /* Process the associated catch regions in reverse order.
2297
           If there's a catch-all handler, then we don't need to
2298
           search outer regions.  Use a magic -3 value to record
2299
           that we haven't done the outer search.  */
2300
        next = -3;
2301
        for (c = region->u.eh_try.last_catch; c ; c = c->prev_catch)
2302
          {
2303
            if (c->type_list == NULL)
2304
              {
2305
                /* Retrieve the filter from the head of the filter list
2306
                   where we have stored it (see assign_filter_values).  */
2307
                int filter = TREE_INT_CST_LOW (TREE_VALUE (c->filter_list));
2308
                next = add_action_record (ar_hash, filter, 0);
2309
              }
2310
            else
2311
              {
2312
                /* Once the outer search is done, trigger an action record for
2313
                   each filter we have.  */
2314
                tree flt_node;
2315
 
2316
                if (next == -3)
2317
                  {
2318
                    next = collect_one_action_chain (ar_hash, region->outer);
2319
 
2320
                    /* If there is no next action, terminate the chain.  */
2321
                    if (next == -1)
2322
                      next = 0;
2323
                    /* If all outer actions are cleanups or must_not_throw,
2324
                       we'll have no action record for it, since we had wanted
2325
                       to encode these states in the call-site record directly.
2326
                       Add a cleanup action to the chain to catch these.  */
2327
                    else if (next <= 0)
2328
                      next = add_action_record (ar_hash, 0, 0);
2329
                  }
2330
 
2331
                flt_node = c->filter_list;
2332
                for (; flt_node; flt_node = TREE_CHAIN (flt_node))
2333
                  {
2334
                    int filter = TREE_INT_CST_LOW (TREE_VALUE (flt_node));
2335
                    next = add_action_record (ar_hash, filter, next);
2336
                  }
2337
              }
2338
          }
2339
        return next;
2340
      }
2341
 
2342
    case ERT_ALLOWED_EXCEPTIONS:
2343
      /* An exception specification adds its filter to the
2344
         beginning of the chain.  */
2345
      next = collect_one_action_chain (ar_hash, region->outer);
2346
 
2347
      /* If there is no next action, terminate the chain.  */
2348
      if (next == -1)
2349
        next = 0;
2350
      /* If all outer actions are cleanups or must_not_throw,
2351
         we'll have no action record for it, since we had wanted
2352
         to encode these states in the call-site record directly.
2353
         Add a cleanup action to the chain to catch these.  */
2354
      else if (next <= 0)
2355
        next = add_action_record (ar_hash, 0, 0);
2356
 
2357
      return add_action_record (ar_hash, region->u.allowed.filter, next);
2358
 
2359
    case ERT_MUST_NOT_THROW:
2360
      /* A must-not-throw region with no inner handlers or cleanups
2361
         requires no call-site entry.  Note that this differs from
2362
         the no handler or cleanup case in that we do require an lsda
2363
         to be generated.  Return a magic -2 value to record this.  */
2364
      return -2;
2365
    }
2366
 
2367
  gcc_unreachable ();
2368
}
2369
 
2370
static int
2371
add_call_site (rtx landing_pad, int action, int section)
2372
{
2373
  call_site_record record;
2374
 
2375
  record = GGC_NEW (struct call_site_record_d);
2376
  record->landing_pad = landing_pad;
2377
  record->action = action;
2378
 
2379
  VEC_safe_push (call_site_record, gc,
2380
                 crtl->eh.call_site_record[section], record);
2381
 
2382
  return call_site_base + VEC_length (call_site_record,
2383
                                      crtl->eh.call_site_record[section]) - 1;
2384
}
2385
 
2386
/* Turn REG_EH_REGION notes back into NOTE_INSN_EH_REGION notes.
2387
   The new note numbers will not refer to region numbers, but
2388
   instead to call site entries.  */
2389
 
2390
static unsigned int
2391
convert_to_eh_region_ranges (void)
2392
{
2393
  rtx insn, iter, note;
2394
  htab_t ar_hash;
2395
  int last_action = -3;
2396
  rtx last_action_insn = NULL_RTX;
2397
  rtx last_landing_pad = NULL_RTX;
2398
  rtx first_no_action_insn = NULL_RTX;
2399
  int call_site = 0;
2400
  int cur_sec = 0;
2401
  rtx section_switch_note = NULL_RTX;
2402
  rtx first_no_action_insn_before_switch = NULL_RTX;
2403
  rtx last_no_action_insn_before_switch = NULL_RTX;
2404
  rtx *pad_map = NULL;
2405
  sbitmap pad_loc = NULL;
2406
  int min_labelno = 0, max_labelno = 0;
2407
  int saved_call_site_base = call_site_base;
2408
 
2409
  crtl->eh.action_record_data = VEC_alloc (uchar, gc, 64);
2410
 
2411
  ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
2412
 
2413
  for (iter = get_insns (); iter ; iter = NEXT_INSN (iter))
2414
    if (INSN_P (iter))
2415
      {
2416
        eh_landing_pad lp;
2417
        eh_region region;
2418
        bool nothrow;
2419
        int this_action;
2420
        rtx this_landing_pad;
2421
 
2422
        insn = iter;
2423
        if (NONJUMP_INSN_P (insn)
2424
            && GET_CODE (PATTERN (insn)) == SEQUENCE)
2425
          insn = XVECEXP (PATTERN (insn), 0, 0);
2426
 
2427
        nothrow = get_eh_region_and_lp_from_rtx (insn, &region, &lp);
2428
        if (nothrow)
2429
          continue;
2430
        if (region)
2431
          this_action = collect_one_action_chain (ar_hash, region);
2432
        else
2433
          this_action = -1;
2434
 
2435
        /* Existence of catch handlers, or must-not-throw regions
2436
           implies that an lsda is needed (even if empty).  */
2437
        if (this_action != -1)
2438
          crtl->uses_eh_lsda = 1;
2439
 
2440
        /* Delay creation of region notes for no-action regions
2441
           until we're sure that an lsda will be required.  */
2442
        else if (last_action == -3)
2443
          {
2444
            first_no_action_insn = iter;
2445
            last_action = -1;
2446
          }
2447
 
2448
        if (this_action >= 0)
2449
          this_landing_pad = lp->landing_pad;
2450
        else
2451
          this_landing_pad = NULL_RTX;
2452
 
2453
        /* Differing actions or landing pads implies a change in call-site
2454
           info, which implies some EH_REGION note should be emitted.  */
2455
        if (last_action != this_action
2456
            || last_landing_pad != this_landing_pad)
2457
          {
2458
            /* If we'd not seen a previous action (-3) or the previous
2459
               action was must-not-throw (-2), then we do not need an
2460
               end note.  */
2461
            if (last_action >= -1)
2462
              {
2463
                /* If we delayed the creation of the begin, do it now.  */
2464
                if (first_no_action_insn_before_switch)
2465
                  {
2466
                    call_site = add_call_site (NULL_RTX, 0, 0);
2467
                    note
2468
                      = emit_note_before (NOTE_INSN_EH_REGION_BEG,
2469
                                          first_no_action_insn_before_switch);
2470
                    NOTE_EH_HANDLER (note) = call_site;
2471
                    if (first_no_action_insn)
2472
                      {
2473
                        note
2474
                          = emit_note_after (NOTE_INSN_EH_REGION_END,
2475
                                             last_no_action_insn_before_switch);
2476
                        NOTE_EH_HANDLER (note) = call_site;
2477
                      }
2478
                    else
2479
                      gcc_assert (last_action_insn
2480
                                  == last_no_action_insn_before_switch);
2481
                  }
2482
                if (first_no_action_insn)
2483
                  {
2484
                    call_site = add_call_site (NULL_RTX, 0, cur_sec);
2485
                    note = emit_note_before (NOTE_INSN_EH_REGION_BEG,
2486
                                             first_no_action_insn);
2487
                    NOTE_EH_HANDLER (note) = call_site;
2488
                    first_no_action_insn = NULL_RTX;
2489
                  }
2490
 
2491
                note = emit_note_after (NOTE_INSN_EH_REGION_END,
2492
                                        last_action_insn);
2493
                NOTE_EH_HANDLER (note) = call_site;
2494
              }
2495
 
2496
            /* If the new action is must-not-throw, then no region notes
2497
               are created.  */
2498
            if (this_action >= -1)
2499
              {
2500
                call_site = add_call_site (this_landing_pad,
2501
                                           this_action < 0 ? 0 : this_action,
2502
                                           cur_sec);
2503
                note = emit_note_before (NOTE_INSN_EH_REGION_BEG, iter);
2504
                NOTE_EH_HANDLER (note) = call_site;
2505
              }
2506
 
2507
            last_action = this_action;
2508
            last_landing_pad = this_landing_pad;
2509
          }
2510
        last_action_insn = iter;
2511
      }
2512
    else if (NOTE_P (iter)
2513
             && NOTE_KIND (iter) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
2514
      {
2515
        gcc_assert (section_switch_note == NULL_RTX);
2516
        gcc_assert (flag_reorder_blocks_and_partition);
2517
        section_switch_note = iter;
2518
        if (first_no_action_insn)
2519
          {
2520
            first_no_action_insn_before_switch = first_no_action_insn;
2521
            last_no_action_insn_before_switch = last_action_insn;
2522
            first_no_action_insn = NULL_RTX;
2523
            gcc_assert (last_action == -1);
2524
            last_action = -3;
2525
          }
2526
        /* Force closing of current EH region before section switch and
2527
           opening a new one afterwards.  */
2528
        else if (last_action != -3)
2529
          last_landing_pad = pc_rtx;
2530
        call_site_base += VEC_length (call_site_record,
2531
                                      crtl->eh.call_site_record[cur_sec]);
2532
        cur_sec++;
2533
        gcc_assert (crtl->eh.call_site_record[cur_sec] == NULL);
2534
        crtl->eh.call_site_record[cur_sec]
2535
          = VEC_alloc (call_site_record, gc, 10);
2536
        max_labelno = max_label_num ();
2537
        min_labelno = get_first_label_num ();
2538
        pad_map = XCNEWVEC (rtx, max_labelno - min_labelno + 1);
2539
        pad_loc = sbitmap_alloc (max_labelno - min_labelno + 1);
2540
      }
2541
    else if (LABEL_P (iter) && pad_map)
2542
      SET_BIT (pad_loc, CODE_LABEL_NUMBER (iter) - min_labelno);
2543
 
2544
  if (last_action >= -1 && ! first_no_action_insn)
2545
    {
2546
      note = emit_note_after (NOTE_INSN_EH_REGION_END, last_action_insn);
2547
      NOTE_EH_HANDLER (note) = call_site;
2548
    }
2549
 
2550
  call_site_base = saved_call_site_base;
2551
 
2552
  if (pad_map)
2553
    {
2554
      /* When doing hot/cold partitioning, ensure landing pads are
2555
         always in the same section as the EH region, .gcc_except_table
2556
         can't express it otherwise.  */
2557
      for (cur_sec = 0; cur_sec < 2; cur_sec++)
2558
        {
2559
          int i, idx;
2560
          int n = VEC_length (call_site_record,
2561
                              crtl->eh.call_site_record[cur_sec]);
2562
          basic_block prev_bb = NULL, padbb;
2563
 
2564
          for (i = 0; i < n; ++i)
2565
            {
2566
              struct call_site_record_d *cs =
2567
                VEC_index (call_site_record,
2568
                           crtl->eh.call_site_record[cur_sec], i);
2569
              rtx jump, note;
2570
 
2571
              if (cs->landing_pad == NULL_RTX)
2572
                continue;
2573
              idx = CODE_LABEL_NUMBER (cs->landing_pad) - min_labelno;
2574
              /* If the landing pad is in the correct section, nothing
2575
                 is needed.  */
2576
              if (TEST_BIT (pad_loc, idx) ^ (cur_sec == 0))
2577
                continue;
2578
              /* Otherwise, if we haven't seen this pad yet, we need to
2579
                 add a new label and jump to the correct section.  */
2580
              if (pad_map[idx] == NULL_RTX)
2581
                {
2582
                  pad_map[idx] = gen_label_rtx ();
2583
                  if (prev_bb == NULL)
2584
                    for (iter = section_switch_note;
2585
                         iter; iter = PREV_INSN (iter))
2586
                      if (NOTE_INSN_BASIC_BLOCK_P (iter))
2587
                        {
2588
                          prev_bb = NOTE_BASIC_BLOCK (iter);
2589
                          break;
2590
                        }
2591
                  if (cur_sec == 0)
2592
                    {
2593
                      note = emit_label_before (pad_map[idx],
2594
                                                section_switch_note);
2595
                      jump = emit_jump_insn_before (gen_jump (cs->landing_pad),
2596
                                                    section_switch_note);
2597
                    }
2598
                  else
2599
                    {
2600
                      jump = emit_jump_insn_after (gen_jump (cs->landing_pad),
2601
                                                   section_switch_note);
2602
                      note = emit_label_after (pad_map[idx],
2603
                                               section_switch_note);
2604
                    }
2605
                  JUMP_LABEL (jump) = cs->landing_pad;
2606
                  add_reg_note (jump, REG_CROSSING_JUMP, NULL_RTX);
2607
                  iter = NEXT_INSN (cs->landing_pad);
2608
                  if (iter && NOTE_INSN_BASIC_BLOCK_P (iter))
2609
                    padbb = NOTE_BASIC_BLOCK (iter);
2610
                  else
2611
                    padbb = NULL;
2612
                  if (padbb && prev_bb
2613
                      && BB_PARTITION (padbb) != BB_UNPARTITIONED)
2614
                    {
2615
                      basic_block bb;
2616
                      int part
2617
                        = BB_PARTITION (padbb) == BB_COLD_PARTITION
2618
                          ? BB_HOT_PARTITION : BB_COLD_PARTITION;
2619
                      edge_iterator ei;
2620
                      edge e;
2621
 
2622
                      bb = create_basic_block (note, jump, prev_bb);
2623
                      make_single_succ_edge (bb, padbb, EDGE_CROSSING);
2624
                      BB_SET_PARTITION (bb, part);
2625
                      for (ei = ei_start (padbb->preds);
2626
                           (e = ei_safe_edge (ei)); )
2627
                        {
2628
                          if ((e->flags & (EDGE_EH|EDGE_CROSSING))
2629
                              == (EDGE_EH|EDGE_CROSSING))
2630
                            {
2631
                              redirect_edge_succ (e, bb);
2632
                              e->flags &= ~EDGE_CROSSING;
2633
                            }
2634
                          else
2635
                            ei_next (&ei);
2636
                        }
2637
                      if (cur_sec == 0)
2638
                        prev_bb = bb;
2639
                    }
2640
                }
2641
              cs->landing_pad = pad_map[idx];
2642
            }
2643
        }
2644
 
2645
      sbitmap_free (pad_loc);
2646
      XDELETEVEC (pad_map);
2647
    }
2648
 
2649
  htab_delete (ar_hash);
2650
  return 0;
2651
}
2652
 
2653
static bool
2654
gate_convert_to_eh_region_ranges (void)
2655
{
2656
  /* Nothing to do for SJLJ exceptions or if no regions created.  */
2657
  return !(USING_SJLJ_EXCEPTIONS || cfun->eh->region_tree == NULL);
2658
}
2659
 
2660
struct rtl_opt_pass pass_convert_to_eh_region_ranges =
2661
{
2662
 {
2663
  RTL_PASS,
2664
  "eh_ranges",                          /* name */
2665
  gate_convert_to_eh_region_ranges,     /* gate */
2666
  convert_to_eh_region_ranges,          /* execute */
2667
  NULL,                                 /* sub */
2668
  NULL,                                 /* next */
2669
  0,                                    /* static_pass_number */
2670
  TV_NONE,                              /* tv_id */
2671
  0,                                    /* properties_required */
2672
  0,                                    /* properties_provided */
2673
  0,                                    /* properties_destroyed */
2674
  0,                                    /* todo_flags_start */
2675
  TODO_dump_func,                       /* todo_flags_finish */
2676
 }
2677
};
2678
 
2679
static void
2680
push_uleb128 (VEC (uchar, gc) **data_area, unsigned int value)
2681
{
2682
  do
2683
    {
2684
      unsigned char byte = value & 0x7f;
2685
      value >>= 7;
2686
      if (value)
2687
        byte |= 0x80;
2688
      VEC_safe_push (uchar, gc, *data_area, byte);
2689
    }
2690
  while (value);
2691
}
2692
 
2693
static void
2694
push_sleb128 (VEC (uchar, gc) **data_area, int value)
2695
{
2696
  unsigned char byte;
2697
  int more;
2698
 
2699
  do
2700
    {
2701
      byte = value & 0x7f;
2702
      value >>= 7;
2703
      more = ! ((value == 0 && (byte & 0x40) == 0)
2704
                || (value == -1 && (byte & 0x40) != 0));
2705
      if (more)
2706
        byte |= 0x80;
2707
      VEC_safe_push (uchar, gc, *data_area, byte);
2708
    }
2709
  while (more);
2710
}
2711
 
2712
 
2713
#ifndef HAVE_AS_LEB128
2714
static int
2715
dw2_size_of_call_site_table (int section)
2716
{
2717
  int n = VEC_length (call_site_record, crtl->eh.call_site_record[section]);
2718
  int size = n * (4 + 4 + 4);
2719
  int i;
2720
 
2721
  for (i = 0; i < n; ++i)
2722
    {
2723
      struct call_site_record_d *cs =
2724
        VEC_index (call_site_record, crtl->eh.call_site_record[section], i);
2725
      size += size_of_uleb128 (cs->action);
2726
    }
2727
 
2728
  return size;
2729
}
2730
 
2731
static int
2732
sjlj_size_of_call_site_table (void)
2733
{
2734
  int n = VEC_length (call_site_record, crtl->eh.call_site_record[0]);
2735
  int size = 0;
2736
  int i;
2737
 
2738
  for (i = 0; i < n; ++i)
2739
    {
2740
      struct call_site_record_d *cs =
2741
        VEC_index (call_site_record, crtl->eh.call_site_record[0], i);
2742
      size += size_of_uleb128 (INTVAL (cs->landing_pad));
2743
      size += size_of_uleb128 (cs->action);
2744
    }
2745
 
2746
  return size;
2747
}
2748
#endif
2749
 
2750
static void
2751
dw2_output_call_site_table (int cs_format, int section)
2752
{
2753
  int n = VEC_length (call_site_record, crtl->eh.call_site_record[section]);
2754
  int i;
2755
  const char *begin;
2756
 
2757
  if (section == 0)
2758
    begin = current_function_func_begin_label;
2759
  else if (first_function_block_is_cold)
2760
    begin = crtl->subsections.hot_section_label;
2761
  else
2762
    begin = crtl->subsections.cold_section_label;
2763
 
2764
  for (i = 0; i < n; ++i)
2765
    {
2766
      struct call_site_record_d *cs =
2767
        VEC_index (call_site_record, crtl->eh.call_site_record[section], i);
2768
      char reg_start_lab[32];
2769
      char reg_end_lab[32];
2770
      char landing_pad_lab[32];
2771
 
2772
      ASM_GENERATE_INTERNAL_LABEL (reg_start_lab, "LEHB", call_site_base + i);
2773
      ASM_GENERATE_INTERNAL_LABEL (reg_end_lab, "LEHE", call_site_base + i);
2774
 
2775
      if (cs->landing_pad)
2776
        ASM_GENERATE_INTERNAL_LABEL (landing_pad_lab, "L",
2777
                                     CODE_LABEL_NUMBER (cs->landing_pad));
2778
 
2779
      /* ??? Perhaps use insn length scaling if the assembler supports
2780
         generic arithmetic.  */
2781
      /* ??? Perhaps use attr_length to choose data1 or data2 instead of
2782
         data4 if the function is small enough.  */
2783
      if (cs_format == DW_EH_PE_uleb128)
2784
        {
2785
          dw2_asm_output_delta_uleb128 (reg_start_lab, begin,
2786
                                        "region %d start", i);
2787
          dw2_asm_output_delta_uleb128 (reg_end_lab, reg_start_lab,
2788
                                        "length");
2789
          if (cs->landing_pad)
2790
            dw2_asm_output_delta_uleb128 (landing_pad_lab, begin,
2791
                                          "landing pad");
2792
          else
2793
            dw2_asm_output_data_uleb128 (0, "landing pad");
2794
        }
2795
      else
2796
        {
2797
          dw2_asm_output_delta (4, reg_start_lab, begin,
2798
                                "region %d start", i);
2799
          dw2_asm_output_delta (4, reg_end_lab, reg_start_lab, "length");
2800
          if (cs->landing_pad)
2801
            dw2_asm_output_delta (4, landing_pad_lab, begin,
2802
                                  "landing pad");
2803
          else
2804
            dw2_asm_output_data (4, 0, "landing pad");
2805
        }
2806
      dw2_asm_output_data_uleb128 (cs->action, "action");
2807
    }
2808
 
2809
  call_site_base += n;
2810
}
2811
 
2812
static void
2813
sjlj_output_call_site_table (void)
2814
{
2815
  int n = VEC_length (call_site_record, crtl->eh.call_site_record[0]);
2816
  int i;
2817
 
2818
  for (i = 0; i < n; ++i)
2819
    {
2820
      struct call_site_record_d *cs =
2821
        VEC_index (call_site_record, crtl->eh.call_site_record[0], i);
2822
 
2823
      dw2_asm_output_data_uleb128 (INTVAL (cs->landing_pad),
2824
                                   "region %d landing pad", i);
2825
      dw2_asm_output_data_uleb128 (cs->action, "action");
2826
    }
2827
 
2828
  call_site_base += n;
2829
}
2830
 
2831
#ifndef TARGET_UNWIND_INFO
2832
/* Switch to the section that should be used for exception tables.  */
2833
 
2834
static void
2835
switch_to_exception_section (const char * ARG_UNUSED (fnname))
2836
{
2837
  section *s;
2838
 
2839
  if (exception_section)
2840
    s = exception_section;
2841
  else
2842
    {
2843
      /* Compute the section and cache it into exception_section,
2844
         unless it depends on the function name.  */
2845
      if (targetm.have_named_sections)
2846
        {
2847
          int flags;
2848
 
2849
          if (EH_TABLES_CAN_BE_READ_ONLY)
2850
            {
2851
              int tt_format =
2852
                ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
2853
              flags = ((! flag_pic
2854
                        || ((tt_format & 0x70) != DW_EH_PE_absptr
2855
                            && (tt_format & 0x70) != DW_EH_PE_aligned))
2856
                       ? 0 : SECTION_WRITE);
2857
            }
2858
          else
2859
            flags = SECTION_WRITE;
2860
 
2861
#ifdef HAVE_LD_EH_GC_SECTIONS
2862
          if (flag_function_sections)
2863
            {
2864
              char *section_name = XNEWVEC (char, strlen (fnname) + 32);
2865
              sprintf (section_name, ".gcc_except_table.%s", fnname);
2866
              s = get_section (section_name, flags, NULL);
2867
              free (section_name);
2868
            }
2869
          else
2870
#endif
2871
            exception_section
2872
              = s = get_section (".gcc_except_table", flags, NULL);
2873
        }
2874
      else
2875
        exception_section
2876
          = s = flag_pic ? data_section : readonly_data_section;
2877
    }
2878
 
2879
  switch_to_section (s);
2880
}
2881
#endif
2882
 
2883
 
2884
/* Output a reference from an exception table to the type_info object TYPE.
2885
   TT_FORMAT and TT_FORMAT_SIZE describe the DWARF encoding method used for
2886
   the value.  */
2887
 
2888
static void
2889
output_ttype (tree type, int tt_format, int tt_format_size)
2890
{
2891
  rtx value;
2892
  bool is_public = true;
2893
 
2894
  if (type == NULL_TREE)
2895
    value = const0_rtx;
2896
  else
2897
    {
2898
      struct varpool_node *node;
2899
 
2900
      /* FIXME lto.  pass_ipa_free_lang_data changes all types to
2901
         runtime types so TYPE should already be a runtime type
2902
         reference.  When pass_ipa_free_lang data is made a default
2903
         pass, we can then remove the call to lookup_type_for_runtime
2904
         below.  */
2905
      if (TYPE_P (type))
2906
        type = lookup_type_for_runtime (type);
2907
 
2908
      value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
2909
 
2910
      /* Let cgraph know that the rtti decl is used.  Not all of the
2911
         paths below go through assemble_integer, which would take
2912
         care of this for us.  */
2913
      STRIP_NOPS (type);
2914
      if (TREE_CODE (type) == ADDR_EXPR)
2915
        {
2916
          type = TREE_OPERAND (type, 0);
2917
          if (TREE_CODE (type) == VAR_DECL)
2918
            {
2919
              node = varpool_node (type);
2920
              if (node)
2921
                varpool_mark_needed_node (node);
2922
              is_public = TREE_PUBLIC (type);
2923
            }
2924
        }
2925
      else
2926
        gcc_assert (TREE_CODE (type) == INTEGER_CST);
2927
    }
2928
 
2929
  /* Allow the target to override the type table entry format.  */
2930
  if (targetm.asm_out.ttype (value))
2931
    return;
2932
 
2933
  if (tt_format == DW_EH_PE_absptr || tt_format == DW_EH_PE_aligned)
2934
    assemble_integer (value, tt_format_size,
2935
                      tt_format_size * BITS_PER_UNIT, 1);
2936
  else
2937
    dw2_asm_output_encoded_addr_rtx (tt_format, value, is_public, NULL);
2938
}
2939
 
2940
static void
2941
output_one_function_exception_table (const char * ARG_UNUSED (fnname),
2942
                                     int section, rtx ARG_UNUSED (personality))
2943
{
2944
  int tt_format, cs_format, lp_format, i;
2945
#ifdef HAVE_AS_LEB128
2946
  char ttype_label[32];
2947
  char cs_after_size_label[32];
2948
  char cs_end_label[32];
2949
#else
2950
  int call_site_len;
2951
#endif
2952
  int have_tt_data;
2953
  int tt_format_size = 0;
2954
 
2955
#ifdef TARGET_UNWIND_INFO
2956
  /* TODO: Move this into target file.  */
2957
  fputs ("\t.personality\t", asm_out_file);
2958
  output_addr_const (asm_out_file, personality);
2959
  fputs ("\n\t.handlerdata\n", asm_out_file);
2960
  /* Note that varasm still thinks we're in the function's code section.
2961
     The ".endp" directive that will immediately follow will take us back.  */
2962
#else
2963
  switch_to_exception_section (fnname);
2964
#endif
2965
 
2966
  /* If the target wants a label to begin the table, emit it here.  */
2967
  targetm.asm_out.except_table_label (asm_out_file);
2968
 
2969
  have_tt_data = (VEC_length (tree, cfun->eh->ttype_data)
2970
                  || (targetm.arm_eabi_unwinder
2971
                      ? VEC_length (tree, cfun->eh->ehspec_data.arm_eabi)
2972
                      : VEC_length (uchar, cfun->eh->ehspec_data.other)));
2973
 
2974
  /* Indicate the format of the @TType entries.  */
2975
  if (! have_tt_data)
2976
    tt_format = DW_EH_PE_omit;
2977
  else
2978
    {
2979
      tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
2980
#ifdef HAVE_AS_LEB128
2981
      ASM_GENERATE_INTERNAL_LABEL (ttype_label,
2982
                                   section ? "LLSDATTC" : "LLSDATT",
2983
                                   current_function_funcdef_no);
2984
#endif
2985
      tt_format_size = size_of_encoded_value (tt_format);
2986
 
2987
      assemble_align (tt_format_size * BITS_PER_UNIT);
2988
    }
2989
 
2990
  targetm.asm_out.internal_label (asm_out_file, section ? "LLSDAC" : "LLSDA",
2991
                                  current_function_funcdef_no);
2992
 
2993
  /* The LSDA header.  */
2994
 
2995
  /* Indicate the format of the landing pad start pointer.  An omitted
2996
     field implies @LPStart == @Start.  */
2997
  /* Currently we always put @LPStart == @Start.  This field would
2998
     be most useful in moving the landing pads completely out of
2999
     line to another section, but it could also be used to minimize
3000
     the size of uleb128 landing pad offsets.  */
3001
  lp_format = DW_EH_PE_omit;
3002
  dw2_asm_output_data (1, lp_format, "@LPStart format (%s)",
3003
                       eh_data_format_name (lp_format));
3004
 
3005
  /* @LPStart pointer would go here.  */
3006
 
3007
  dw2_asm_output_data (1, tt_format, "@TType format (%s)",
3008
                       eh_data_format_name (tt_format));
3009
 
3010
#ifndef HAVE_AS_LEB128
3011
  if (USING_SJLJ_EXCEPTIONS)
3012
    call_site_len = sjlj_size_of_call_site_table ();
3013
  else
3014
    call_site_len = dw2_size_of_call_site_table (section);
3015
#endif
3016
 
3017
  /* A pc-relative 4-byte displacement to the @TType data.  */
3018
  if (have_tt_data)
3019
    {
3020
#ifdef HAVE_AS_LEB128
3021
      char ttype_after_disp_label[32];
3022
      ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label,
3023
                                   section ? "LLSDATTDC" : "LLSDATTD",
3024
                                   current_function_funcdef_no);
3025
      dw2_asm_output_delta_uleb128 (ttype_label, ttype_after_disp_label,
3026
                                    "@TType base offset");
3027
      ASM_OUTPUT_LABEL (asm_out_file, ttype_after_disp_label);
3028
#else
3029
      /* Ug.  Alignment queers things.  */
3030
      unsigned int before_disp, after_disp, last_disp, disp;
3031
 
3032
      before_disp = 1 + 1;
3033
      after_disp = (1 + size_of_uleb128 (call_site_len)
3034
                    + call_site_len
3035
                    + VEC_length (uchar, crtl->eh.action_record_data)
3036
                    + (VEC_length (tree, cfun->eh->ttype_data)
3037
                       * tt_format_size));
3038
 
3039
      disp = after_disp;
3040
      do
3041
        {
3042
          unsigned int disp_size, pad;
3043
 
3044
          last_disp = disp;
3045
          disp_size = size_of_uleb128 (disp);
3046
          pad = before_disp + disp_size + after_disp;
3047
          if (pad % tt_format_size)
3048
            pad = tt_format_size - (pad % tt_format_size);
3049
          else
3050
            pad = 0;
3051
          disp = after_disp + pad;
3052
        }
3053
      while (disp != last_disp);
3054
 
3055
      dw2_asm_output_data_uleb128 (disp, "@TType base offset");
3056
#endif
3057
    }
3058
 
3059
  /* Indicate the format of the call-site offsets.  */
3060
#ifdef HAVE_AS_LEB128
3061
  cs_format = DW_EH_PE_uleb128;
3062
#else
3063
  cs_format = DW_EH_PE_udata4;
3064
#endif
3065
  dw2_asm_output_data (1, cs_format, "call-site format (%s)",
3066
                       eh_data_format_name (cs_format));
3067
 
3068
#ifdef HAVE_AS_LEB128
3069
  ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label,
3070
                               section ? "LLSDACSBC" : "LLSDACSB",
3071
                               current_function_funcdef_no);
3072
  ASM_GENERATE_INTERNAL_LABEL (cs_end_label,
3073
                               section ? "LLSDACSEC" : "LLSDACSE",
3074
                               current_function_funcdef_no);
3075
  dw2_asm_output_delta_uleb128 (cs_end_label, cs_after_size_label,
3076
                                "Call-site table length");
3077
  ASM_OUTPUT_LABEL (asm_out_file, cs_after_size_label);
3078
  if (USING_SJLJ_EXCEPTIONS)
3079
    sjlj_output_call_site_table ();
3080
  else
3081
    dw2_output_call_site_table (cs_format, section);
3082
  ASM_OUTPUT_LABEL (asm_out_file, cs_end_label);
3083
#else
3084
  dw2_asm_output_data_uleb128 (call_site_len, "Call-site table length");
3085
  if (USING_SJLJ_EXCEPTIONS)
3086
    sjlj_output_call_site_table ();
3087
  else
3088
    dw2_output_call_site_table (cs_format, section);
3089
#endif
3090
 
3091
  /* ??? Decode and interpret the data for flag_debug_asm.  */
3092
  {
3093
    uchar uc;
3094
    for (i = 0; VEC_iterate (uchar, crtl->eh.action_record_data, i, uc); ++i)
3095
      dw2_asm_output_data (1, uc, i ? NULL : "Action record table");
3096
  }
3097
 
3098
  if (have_tt_data)
3099
    assemble_align (tt_format_size * BITS_PER_UNIT);
3100
 
3101
  i = VEC_length (tree, cfun->eh->ttype_data);
3102
  while (i-- > 0)
3103
    {
3104
      tree type = VEC_index (tree, cfun->eh->ttype_data, i);
3105
      output_ttype (type, tt_format, tt_format_size);
3106
    }
3107
 
3108
#ifdef HAVE_AS_LEB128
3109
  if (have_tt_data)
3110
      ASM_OUTPUT_LABEL (asm_out_file, ttype_label);
3111
#endif
3112
 
3113
  /* ??? Decode and interpret the data for flag_debug_asm.  */
3114
  if (targetm.arm_eabi_unwinder)
3115
    {
3116
      tree type;
3117
      for (i = 0;
3118
           VEC_iterate (tree, cfun->eh->ehspec_data.arm_eabi, i, type); ++i)
3119
        output_ttype (type, tt_format, tt_format_size);
3120
    }
3121
  else
3122
    {
3123
      uchar uc;
3124
      for (i = 0;
3125
           VEC_iterate (uchar, cfun->eh->ehspec_data.other, i, uc); ++i)
3126
        dw2_asm_output_data (1, uc,
3127
                             i ? NULL : "Exception specification table");
3128
    }
3129
}
3130
 
3131
void
3132
output_function_exception_table (const char * ARG_UNUSED (fnname))
3133
{
3134
  rtx personality = get_personality_function (current_function_decl);
3135
 
3136
  /* Not all functions need anything.  */
3137
  if (! crtl->uses_eh_lsda)
3138
    return;
3139
 
3140
  if (personality)
3141
    assemble_external_libcall (personality);
3142
 
3143
  output_one_function_exception_table (fnname, 0, personality);
3144
  if (crtl->eh.call_site_record[1] != NULL)
3145
    output_one_function_exception_table (fnname, 1, personality);
3146
 
3147
  switch_to_section (current_function_section ());
3148
}
3149
 
3150
void
3151
set_eh_throw_stmt_table (struct function *fun, struct htab *table)
3152
{
3153
  fun->eh->throw_stmt_table = table;
3154
}
3155
 
3156
htab_t
3157
get_eh_throw_stmt_table (struct function *fun)
3158
{
3159
  return fun->eh->throw_stmt_table;
3160
}
3161
 
3162
/* Determine if the function needs an EH personality function.  */
3163
 
3164
enum eh_personality_kind
3165
function_needs_eh_personality (struct function *fn)
3166
{
3167
  enum eh_personality_kind kind = eh_personality_none;
3168
  eh_region i;
3169
 
3170
  FOR_ALL_EH_REGION_FN (i, fn)
3171
    {
3172
      switch (i->type)
3173
        {
3174
        case ERT_CLEANUP:
3175
          /* Can do with any personality including the generic C one.  */
3176
          kind = eh_personality_any;
3177
          break;
3178
 
3179
        case ERT_TRY:
3180
        case ERT_ALLOWED_EXCEPTIONS:
3181
          /* Always needs a EH personality function.  The generic C
3182
             personality doesn't handle these even for empty type lists.  */
3183
          return eh_personality_lang;
3184
 
3185
        case ERT_MUST_NOT_THROW:
3186
          /* Always needs a EH personality function.  The language may specify
3187
             what abort routine that must be used, e.g. std::terminate.  */
3188
          return eh_personality_lang;
3189
        }
3190
    }
3191
 
3192
  return kind;
3193
}
3194
 
3195
/* Dump EH information to OUT.  */
3196
 
3197
void
3198
dump_eh_tree (FILE * out, struct function *fun)
3199
{
3200
  eh_region i;
3201
  int depth = 0;
3202
  static const char *const type_name[] = {
3203
    "cleanup", "try", "allowed_exceptions", "must_not_throw"
3204
  };
3205
 
3206
  i = fun->eh->region_tree;
3207
  if (!i)
3208
    return;
3209
 
3210
  fprintf (out, "Eh tree:\n");
3211
  while (1)
3212
    {
3213
      fprintf (out, "  %*s %i %s", depth * 2, "",
3214
               i->index, type_name[(int) i->type]);
3215
 
3216
      if (i->landing_pads)
3217
        {
3218
          eh_landing_pad lp;
3219
 
3220
          fprintf (out, " land:");
3221
          if (current_ir_type () == IR_GIMPLE)
3222
            {
3223
              for (lp = i->landing_pads; lp ; lp = lp->next_lp)
3224
                {
3225
                  fprintf (out, "{%i,", lp->index);
3226
                  print_generic_expr (out, lp->post_landing_pad, 0);
3227
                  fputc ('}', out);
3228
                  if (lp->next_lp)
3229
                    fputc (',', out);
3230
                }
3231
            }
3232
          else
3233
            {
3234
              for (lp = i->landing_pads; lp ; lp = lp->next_lp);
3235
                {
3236
                  fprintf (out, "{%i,", lp->index);
3237
                  if (lp->landing_pad)
3238
                    fprintf (out, "%i%s,", INSN_UID (lp->landing_pad),
3239
                             NOTE_P (lp->landing_pad) ? "(del)" : "");
3240
                  else
3241
                    fprintf (out, "(nil),");
3242
                  if (lp->post_landing_pad)
3243
                    {
3244
                      rtx lab = label_rtx (lp->post_landing_pad);
3245
                      fprintf (out, "%i%s}", INSN_UID (lab),
3246
                               NOTE_P (lab) ? "(del)" : "");
3247
                    }
3248
                  else
3249
                    fprintf (out, "(nil)}");
3250
                  if (lp->next_lp)
3251
                    fputc (',', out);
3252
                }
3253
            }
3254
        }
3255
 
3256
      switch (i->type)
3257
        {
3258
        case ERT_CLEANUP:
3259
        case ERT_MUST_NOT_THROW:
3260
          break;
3261
 
3262
        case ERT_TRY:
3263
          {
3264
            eh_catch c;
3265
            fprintf (out, " catch:");
3266
            for (c = i->u.eh_try.first_catch; c; c = c->next_catch)
3267
              {
3268
                fputc ('{', out);
3269
                if (c->label)
3270
                  {
3271
                    fprintf (out, "lab:");
3272
                    print_generic_expr (out, c->label, 0);
3273
                    fputc (';', out);
3274
                  }
3275
                print_generic_expr (out, c->type_list, 0);
3276
                fputc ('}', out);
3277
                if (c->next_catch)
3278
                  fputc (',', out);
3279
              }
3280
          }
3281
          break;
3282
 
3283
        case ERT_ALLOWED_EXCEPTIONS:
3284
          fprintf (out, " filter :%i types:", i->u.allowed.filter);
3285
          print_generic_expr (out, i->u.allowed.type_list, 0);
3286
          break;
3287
        }
3288
      fputc ('\n', out);
3289
 
3290
      /* If there are sub-regions, process them.  */
3291
      if (i->inner)
3292
        i = i->inner, depth++;
3293
      /* If there are peers, process them.  */
3294
      else if (i->next_peer)
3295
        i = i->next_peer;
3296
      /* Otherwise, step back up the tree to the next peer.  */
3297
      else
3298
        {
3299
          do
3300
            {
3301
              i = i->outer;
3302
              depth--;
3303
              if (i == NULL)
3304
                return;
3305
            }
3306
          while (i->next_peer == NULL);
3307
          i = i->next_peer;
3308
        }
3309
    }
3310
}
3311
 
3312
/* Dump the EH tree for FN on stderr.  */
3313
 
3314
void
3315
debug_eh_tree (struct function *fn)
3316
{
3317
  dump_eh_tree (stderr, fn);
3318
}
3319
 
3320
/* Verify invariants on EH datastructures.  */
3321
 
3322
void
3323
verify_eh_tree (struct function *fun)
3324
{
3325
  eh_region r, outer;
3326
  int nvisited_lp, nvisited_r;
3327
  int count_lp, count_r, depth, i;
3328
  eh_landing_pad lp;
3329
  bool err = false;
3330
 
3331
  if (!fun->eh->region_tree)
3332
    return;
3333
 
3334
  count_r = 0;
3335
  for (i = 1; VEC_iterate (eh_region, fun->eh->region_array, i, r); ++i)
3336
    if (r)
3337
      {
3338
        if (r->index == i)
3339
          count_r++;
3340
        else
3341
          {
3342
            error ("region_array is corrupted for region %i", r->index);
3343
            err = true;
3344
          }
3345
      }
3346
 
3347
  count_lp = 0;
3348
  for (i = 1; VEC_iterate (eh_landing_pad, fun->eh->lp_array, i, lp); ++i)
3349
    if (lp)
3350
      {
3351
        if (lp->index == i)
3352
          count_lp++;
3353
        else
3354
          {
3355
            error ("lp_array is corrupted for lp %i", lp->index);
3356
            err = true;
3357
          }
3358
      }
3359
 
3360
  depth = nvisited_lp = nvisited_r = 0;
3361
  outer = NULL;
3362
  r = fun->eh->region_tree;
3363
  while (1)
3364
    {
3365
      if (VEC_index (eh_region, fun->eh->region_array, r->index) != r)
3366
        {
3367
          error ("region_array is corrupted for region %i", r->index);
3368
          err = true;
3369
        }
3370
      if (r->outer != outer)
3371
        {
3372
          error ("outer block of region %i is wrong", r->index);
3373
          err = true;
3374
        }
3375
      if (depth < 0)
3376
        {
3377
          error ("negative nesting depth of region %i", r->index);
3378
          err = true;
3379
        }
3380
      nvisited_r++;
3381
 
3382
      for (lp = r->landing_pads; lp ; lp = lp->next_lp)
3383
        {
3384
          if (VEC_index (eh_landing_pad, fun->eh->lp_array, lp->index) != lp)
3385
            {
3386
              error ("lp_array is corrupted for lp %i", lp->index);
3387
              err = true;
3388
            }
3389
          if (lp->region != r)
3390
            {
3391
              error ("region of lp %i is wrong", lp->index);
3392
              err = true;
3393
            }
3394
          nvisited_lp++;
3395
        }
3396
 
3397
      if (r->inner)
3398
        outer = r, r = r->inner, depth++;
3399
      else if (r->next_peer)
3400
        r = r->next_peer;
3401
      else
3402
        {
3403
          do
3404
            {
3405
              r = r->outer;
3406
              if (r == NULL)
3407
                goto region_done;
3408
              depth--;
3409
              outer = r->outer;
3410
            }
3411
          while (r->next_peer == NULL);
3412
          r = r->next_peer;
3413
        }
3414
    }
3415
 region_done:
3416
  if (depth != 0)
3417
    {
3418
      error ("tree list ends on depth %i", depth);
3419
      err = true;
3420
    }
3421
  if (count_r != nvisited_r)
3422
    {
3423
      error ("region_array does not match region_tree");
3424
      err = true;
3425
    }
3426
  if (count_lp != nvisited_lp)
3427
    {
3428
      error ("lp_array does not match region_tree");
3429
      err = true;
3430
    }
3431
 
3432
  if (err)
3433
    {
3434
      dump_eh_tree (stderr, fun);
3435
      internal_error ("verify_eh_tree failed");
3436
    }
3437
}
3438
 
3439
#include "gt-except.h"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.