| 1 |
684 |
jeremybenn |
/* Exception Handling interface routines.
|
| 2 |
|
|
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
| 3 |
|
|
2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
| 4 |
|
|
Contributed by Mike Stump <mrs@cygnus.com>.
|
| 5 |
|
|
|
| 6 |
|
|
This file is part of GCC.
|
| 7 |
|
|
|
| 8 |
|
|
GCC is free software; you can redistribute it and/or modify it under
|
| 9 |
|
|
the terms of the GNU General Public License as published by the Free
|
| 10 |
|
|
Software Foundation; either version 3, or (at your option) any later
|
| 11 |
|
|
version.
|
| 12 |
|
|
|
| 13 |
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
| 14 |
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
| 15 |
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
| 16 |
|
|
for more details.
|
| 17 |
|
|
|
| 18 |
|
|
You should have received a copy of the GNU General Public License
|
| 19 |
|
|
along with GCC; see the file COPYING3. If not see
|
| 20 |
|
|
<http://www.gnu.org/licenses/>. */
|
| 21 |
|
|
|
| 22 |
|
|
/* No include guards here, but define an include file marker anyway, so
|
| 23 |
|
|
that the compiler can keep track of where this file is included. This
|
| 24 |
|
|
is e.g. used to avoid including this file in front-end specific files. */
|
| 25 |
|
|
#ifndef GCC_EXCEPT_H
|
| 26 |
|
|
# define GCC_EXCEPT_H
|
| 27 |
|
|
#endif
|
| 28 |
|
|
|
| 29 |
|
|
#include "hashtab.h"
|
| 30 |
|
|
#include "vecprim.h"
|
| 31 |
|
|
#include "vecir.h"
|
| 32 |
|
|
|
| 33 |
|
|
struct function;
|
| 34 |
|
|
struct eh_region_d;
|
| 35 |
|
|
struct pointer_map_t;
|
| 36 |
|
|
|
| 37 |
|
|
/* The type of an exception region. */
|
| 38 |
|
|
enum eh_region_type
|
| 39 |
|
|
{
|
| 40 |
|
|
/* CLEANUP regions implement e.g. destructors run when exiting a block.
|
| 41 |
|
|
They can be generated from both GIMPLE_TRY_FINALLY and GIMPLE_TRY_CATCH
|
| 42 |
|
|
nodes. It is expected by the runtime that cleanup regions will *not*
|
| 43 |
|
|
resume normal program flow, but will continue propagation of the
|
| 44 |
|
|
exception. */
|
| 45 |
|
|
ERT_CLEANUP,
|
| 46 |
|
|
|
| 47 |
|
|
/* TRY regions implement catching an exception. The list of types associated
|
| 48 |
|
|
with the attached catch handlers is examined in order by the runtime and
|
| 49 |
|
|
control is transfered to the appropriate handler. Note that a NULL type
|
| 50 |
|
|
list is a catch-all handler, and that it will catch *all* exceptions
|
| 51 |
|
|
including those originating from a different language. */
|
| 52 |
|
|
ERT_TRY,
|
| 53 |
|
|
|
| 54 |
|
|
/* ALLOWED_EXCEPTIONS regions implement exception filtering, e.g. the
|
| 55 |
|
|
throw(type-list) specification that can be added to C++ functions.
|
| 56 |
|
|
The runtime examines the thrown exception vs the type list, and if
|
| 57 |
|
|
the exception does not match, transfers control to the handler. The
|
| 58 |
|
|
normal handler for C++ calls __cxa_call_unexpected. */
|
| 59 |
|
|
ERT_ALLOWED_EXCEPTIONS,
|
| 60 |
|
|
|
| 61 |
|
|
/* MUST_NOT_THROW regions prevent all exceptions from propagating. This
|
| 62 |
|
|
region type is used in C++ to surround destructors being run inside a
|
| 63 |
|
|
CLEANUP region. This differs from an ALLOWED_EXCEPTIONS region with
|
| 64 |
|
|
an empty type list in that the runtime is prepared to terminate the
|
| 65 |
|
|
program directly. We only generate code for MUST_NOT_THROW regions
|
| 66 |
|
|
along control paths that are already handling an exception within the
|
| 67 |
|
|
current function. */
|
| 68 |
|
|
ERT_MUST_NOT_THROW
|
| 69 |
|
|
};
|
| 70 |
|
|
|
| 71 |
|
|
|
| 72 |
|
|
/* A landing pad for a given exception region. Any transfer of control
|
| 73 |
|
|
from the EH runtime to the function happens at a landing pad. */
|
| 74 |
|
|
|
| 75 |
|
|
struct GTY(()) eh_landing_pad_d
|
| 76 |
|
|
{
|
| 77 |
|
|
/* The linked list of all landing pads associated with the region. */
|
| 78 |
|
|
struct eh_landing_pad_d *next_lp;
|
| 79 |
|
|
|
| 80 |
|
|
/* The region with which this landing pad is associated. */
|
| 81 |
|
|
struct eh_region_d *region;
|
| 82 |
|
|
|
| 83 |
|
|
/* At the gimple level, the location to which control will be transfered
|
| 84 |
|
|
for this landing pad. There can be both EH and normal edges into the
|
| 85 |
|
|
block containing the post-landing-pad label. */
|
| 86 |
|
|
tree post_landing_pad;
|
| 87 |
|
|
|
| 88 |
|
|
/* At the rtl level, the location to which the runtime will transfer
|
| 89 |
|
|
control. This differs from the post-landing-pad in that the target's
|
| 90 |
|
|
EXCEPTION_RECEIVER pattern will be expanded here, as well as other
|
| 91 |
|
|
bookkeeping specific to exceptions. There must not be normal edges
|
| 92 |
|
|
into the block containing the landing-pad label. */
|
| 93 |
|
|
rtx landing_pad;
|
| 94 |
|
|
|
| 95 |
|
|
/* The index of this landing pad within fun->eh->lp_array. */
|
| 96 |
|
|
int index;
|
| 97 |
|
|
};
|
| 98 |
|
|
|
| 99 |
|
|
/* A catch handler associated with an ERT_TRY region. */
|
| 100 |
|
|
|
| 101 |
|
|
struct GTY(()) eh_catch_d
|
| 102 |
|
|
{
|
| 103 |
|
|
/* The double-linked list of all catch handlers for the region. */
|
| 104 |
|
|
struct eh_catch_d *next_catch;
|
| 105 |
|
|
struct eh_catch_d *prev_catch;
|
| 106 |
|
|
|
| 107 |
|
|
/* A TREE_LIST of runtime type objects that this catch handler
|
| 108 |
|
|
will catch, or NULL if all exceptions are caught. */
|
| 109 |
|
|
tree type_list;
|
| 110 |
|
|
|
| 111 |
|
|
/* A TREE_LIST of INTEGER_CSTs that correspond to the type_list entries,
|
| 112 |
|
|
having been mapped by assign_filter_values. These integers are to be
|
| 113 |
|
|
compared against the __builtin_eh_filter value. */
|
| 114 |
|
|
tree filter_list;
|
| 115 |
|
|
|
| 116 |
|
|
/* The code that should be executed if this catch handler matches the
|
| 117 |
|
|
thrown exception. This label is only maintained until
|
| 118 |
|
|
pass_lower_eh_dispatch, at which point it is cleared. */
|
| 119 |
|
|
tree label;
|
| 120 |
|
|
};
|
| 121 |
|
|
|
| 122 |
|
|
/* Describes one exception region. */
|
| 123 |
|
|
|
| 124 |
|
|
struct GTY(()) eh_region_d
|
| 125 |
|
|
{
|
| 126 |
|
|
/* The immediately surrounding region. */
|
| 127 |
|
|
struct eh_region_d *outer;
|
| 128 |
|
|
|
| 129 |
|
|
/* The list of immediately contained regions. */
|
| 130 |
|
|
struct eh_region_d *inner;
|
| 131 |
|
|
struct eh_region_d *next_peer;
|
| 132 |
|
|
|
| 133 |
|
|
/* The index of this region within fun->eh->region_array. */
|
| 134 |
|
|
int index;
|
| 135 |
|
|
|
| 136 |
|
|
/* Each region does exactly one thing. */
|
| 137 |
|
|
enum eh_region_type type;
|
| 138 |
|
|
|
| 139 |
|
|
/* Holds the action to perform based on the preceding type. */
|
| 140 |
|
|
union eh_region_u {
|
| 141 |
|
|
struct eh_region_u_try {
|
| 142 |
|
|
/* The double-linked list of all catch handlers for this region. */
|
| 143 |
|
|
struct eh_catch_d *first_catch;
|
| 144 |
|
|
struct eh_catch_d *last_catch;
|
| 145 |
|
|
} GTY ((tag ("ERT_TRY"))) eh_try;
|
| 146 |
|
|
|
| 147 |
|
|
struct eh_region_u_allowed {
|
| 148 |
|
|
/* A TREE_LIST of runtime type objects allowed to pass. */
|
| 149 |
|
|
tree type_list;
|
| 150 |
|
|
/* The code that should be executed if the thrown exception does
|
| 151 |
|
|
not match the type list. This label is only maintained until
|
| 152 |
|
|
pass_lower_eh_dispatch, at which point it is cleared. */
|
| 153 |
|
|
tree label;
|
| 154 |
|
|
/* The integer that will be passed by the runtime to signal that
|
| 155 |
|
|
we should execute the code at LABEL. This integer is assigned
|
| 156 |
|
|
by assign_filter_values and is to be compared against the
|
| 157 |
|
|
__builtin_eh_filter value. */
|
| 158 |
|
|
int filter;
|
| 159 |
|
|
} GTY ((tag ("ERT_ALLOWED_EXCEPTIONS"))) allowed;
|
| 160 |
|
|
|
| 161 |
|
|
struct eh_region_u_must_not_throw {
|
| 162 |
|
|
/* A function decl to be invoked if this region is actually reachable
|
| 163 |
|
|
from within the function, rather than implementable from the runtime.
|
| 164 |
|
|
The normal way for this to happen is for there to be a CLEANUP region
|
| 165 |
|
|
contained within this MUST_NOT_THROW region. Note that if the
|
| 166 |
|
|
runtime handles the MUST_NOT_THROW region, we have no control over
|
| 167 |
|
|
what termination function is called; it will be decided by the
|
| 168 |
|
|
personality function in effect for this CIE. */
|
| 169 |
|
|
tree failure_decl;
|
| 170 |
|
|
/* The location assigned to the call of FAILURE_DECL, if expanded. */
|
| 171 |
|
|
location_t failure_loc;
|
| 172 |
|
|
} GTY ((tag ("ERT_MUST_NOT_THROW"))) must_not_throw;
|
| 173 |
|
|
} GTY ((desc ("%0.type"))) u;
|
| 174 |
|
|
|
| 175 |
|
|
/* The list of landing pads associated with this region. */
|
| 176 |
|
|
struct eh_landing_pad_d *landing_pads;
|
| 177 |
|
|
|
| 178 |
|
|
/* EXC_PTR and FILTER values copied from the runtime for this region.
|
| 179 |
|
|
Each region gets its own psuedos so that if there are nested exceptions
|
| 180 |
|
|
we do not overwrite the values of the first exception. */
|
| 181 |
|
|
rtx exc_ptr_reg, filter_reg;
|
| 182 |
|
|
|
| 183 |
|
|
/* True if this region should use __cxa_end_cleanup instead
|
| 184 |
|
|
of _Unwind_Resume. */
|
| 185 |
|
|
bool use_cxa_end_cleanup;
|
| 186 |
|
|
};
|
| 187 |
|
|
|
| 188 |
|
|
typedef struct eh_landing_pad_d *eh_landing_pad;
|
| 189 |
|
|
typedef struct eh_catch_d *eh_catch;
|
| 190 |
|
|
typedef struct eh_region_d *eh_region;
|
| 191 |
|
|
|
| 192 |
|
|
DEF_VEC_P(eh_region);
|
| 193 |
|
|
DEF_VEC_ALLOC_P(eh_region, gc);
|
| 194 |
|
|
DEF_VEC_ALLOC_P(eh_region, heap);
|
| 195 |
|
|
|
| 196 |
|
|
DEF_VEC_P(eh_landing_pad);
|
| 197 |
|
|
DEF_VEC_ALLOC_P(eh_landing_pad, gc);
|
| 198 |
|
|
|
| 199 |
|
|
|
| 200 |
|
|
/* The exception status for each function. */
|
| 201 |
|
|
|
| 202 |
|
|
struct GTY(()) eh_status
|
| 203 |
|
|
{
|
| 204 |
|
|
/* The tree of all regions for this function. */
|
| 205 |
|
|
eh_region region_tree;
|
| 206 |
|
|
|
| 207 |
|
|
/* The same information as an indexable array. */
|
| 208 |
|
|
VEC(eh_region,gc) *region_array;
|
| 209 |
|
|
|
| 210 |
|
|
/* The landing pads as an indexable array. */
|
| 211 |
|
|
VEC(eh_landing_pad,gc) *lp_array;
|
| 212 |
|
|
|
| 213 |
|
|
/* At the gimple level, a mapping from gimple statement to landing pad
|
| 214 |
|
|
or must-not-throw region. See record_stmt_eh_region. */
|
| 215 |
|
|
htab_t GTY((param_is (struct throw_stmt_node))) throw_stmt_table;
|
| 216 |
|
|
|
| 217 |
|
|
/* All of the runtime type data used by the function. These objects
|
| 218 |
|
|
are emitted to the lang-specific-data-area for the function. */
|
| 219 |
|
|
VEC(tree,gc) *ttype_data;
|
| 220 |
|
|
|
| 221 |
|
|
/* The table of all action chains. These encode the eh_region tree in
|
| 222 |
|
|
a compact form for use by the runtime, and is also emitted to the
|
| 223 |
|
|
lang-specific-data-area. Note that the ARM EABI uses a different
|
| 224 |
|
|
format for the encoding than all other ports. */
|
| 225 |
|
|
union eh_status_u {
|
| 226 |
|
|
VEC(tree,gc) * GTY((tag ("1"))) arm_eabi;
|
| 227 |
|
|
VEC(uchar,gc) * GTY((tag ("0"))) other;
|
| 228 |
|
|
} GTY ((desc ("targetm.arm_eabi_unwinder"))) ehspec_data;
|
| 229 |
|
|
};
|
| 230 |
|
|
|
| 231 |
|
|
|
| 232 |
|
|
/* Invokes CALLBACK for every exception handler label. Only used by old
|
| 233 |
|
|
loop hackery; should not be used by new code. */
|
| 234 |
|
|
extern void for_each_eh_label (void (*) (rtx));
|
| 235 |
|
|
|
| 236 |
|
|
extern void init_eh_for_function (void);
|
| 237 |
|
|
|
| 238 |
|
|
extern void remove_eh_landing_pad (eh_landing_pad);
|
| 239 |
|
|
extern void remove_eh_handler (eh_region);
|
| 240 |
|
|
|
| 241 |
|
|
extern bool current_function_has_exception_handlers (void);
|
| 242 |
|
|
extern void output_function_exception_table (const char *);
|
| 243 |
|
|
|
| 244 |
|
|
extern rtx expand_builtin_eh_pointer (tree);
|
| 245 |
|
|
extern rtx expand_builtin_eh_filter (tree);
|
| 246 |
|
|
extern rtx expand_builtin_eh_copy_values (tree);
|
| 247 |
|
|
extern void expand_builtin_unwind_init (void);
|
| 248 |
|
|
extern rtx expand_builtin_eh_return_data_regno (tree);
|
| 249 |
|
|
extern rtx expand_builtin_extract_return_addr (tree);
|
| 250 |
|
|
extern void expand_builtin_init_dwarf_reg_sizes (tree);
|
| 251 |
|
|
extern rtx expand_builtin_frob_return_addr (tree);
|
| 252 |
|
|
extern rtx expand_builtin_dwarf_sp_column (void);
|
| 253 |
|
|
extern void expand_builtin_eh_return (tree, tree);
|
| 254 |
|
|
extern void expand_eh_return (void);
|
| 255 |
|
|
extern rtx expand_builtin_extend_pointer (tree);
|
| 256 |
|
|
extern void expand_dw2_landing_pad_for_region (eh_region);
|
| 257 |
|
|
|
| 258 |
|
|
typedef tree (*duplicate_eh_regions_map) (tree, void *);
|
| 259 |
|
|
extern struct pointer_map_t *duplicate_eh_regions
|
| 260 |
|
|
(struct function *, eh_region, int, duplicate_eh_regions_map, void *);
|
| 261 |
|
|
|
| 262 |
|
|
extern void sjlj_emit_function_exit_after (rtx);
|
| 263 |
|
|
|
| 264 |
|
|
extern eh_region gen_eh_region_cleanup (eh_region);
|
| 265 |
|
|
extern eh_region gen_eh_region_try (eh_region);
|
| 266 |
|
|
extern eh_region gen_eh_region_allowed (eh_region, tree);
|
| 267 |
|
|
extern eh_region gen_eh_region_must_not_throw (eh_region);
|
| 268 |
|
|
|
| 269 |
|
|
extern eh_catch gen_eh_region_catch (eh_region, tree);
|
| 270 |
|
|
extern eh_landing_pad gen_eh_landing_pad (eh_region);
|
| 271 |
|
|
|
| 272 |
|
|
extern eh_region get_eh_region_from_number_fn (struct function *, int);
|
| 273 |
|
|
extern eh_region get_eh_region_from_number (int);
|
| 274 |
|
|
extern eh_landing_pad get_eh_landing_pad_from_number_fn (struct function*,int);
|
| 275 |
|
|
extern eh_landing_pad get_eh_landing_pad_from_number (int);
|
| 276 |
|
|
extern eh_region get_eh_region_from_lp_number_fn (struct function *, int);
|
| 277 |
|
|
extern eh_region get_eh_region_from_lp_number (int);
|
| 278 |
|
|
|
| 279 |
|
|
extern eh_region eh_region_outermost (struct function *, eh_region, eh_region);
|
| 280 |
|
|
|
| 281 |
|
|
extern void make_reg_eh_region_note (rtx insn, int ecf_flags, int lp_nr);
|
| 282 |
|
|
extern void make_reg_eh_region_note_nothrow_nononlocal (rtx);
|
| 283 |
|
|
|
| 284 |
|
|
extern void verify_eh_tree (struct function *);
|
| 285 |
|
|
extern void dump_eh_tree (FILE *, struct function *);
|
| 286 |
|
|
void debug_eh_tree (struct function *);
|
| 287 |
|
|
extern void add_type_for_runtime (tree);
|
| 288 |
|
|
extern tree lookup_type_for_runtime (tree);
|
| 289 |
|
|
extern void assign_filter_values (void);
|
| 290 |
|
|
|
| 291 |
|
|
extern eh_region get_eh_region_from_rtx (const_rtx);
|
| 292 |
|
|
extern eh_landing_pad get_eh_landing_pad_from_rtx (const_rtx);
|
| 293 |
|
|
|
| 294 |
|
|
struct GTY(()) throw_stmt_node {
|
| 295 |
|
|
gimple stmt;
|
| 296 |
|
|
int lp_nr;
|
| 297 |
|
|
};
|
| 298 |
|
|
|
| 299 |
|
|
extern struct htab *get_eh_throw_stmt_table (struct function *);
|
| 300 |
|
|
extern void set_eh_throw_stmt_table (struct function *, struct htab *);
|
| 301 |
|
|
|
| 302 |
|
|
enum eh_personality_kind {
|
| 303 |
|
|
eh_personality_none,
|
| 304 |
|
|
eh_personality_any,
|
| 305 |
|
|
eh_personality_lang
|
| 306 |
|
|
};
|
| 307 |
|
|
|
| 308 |
|
|
extern enum eh_personality_kind
|
| 309 |
|
|
function_needs_eh_personality (struct function *);
|
| 310 |
|
|
|
| 311 |
|
|
/* Pre-order iteration within the eh_region tree. */
|
| 312 |
|
|
|
| 313 |
|
|
static inline eh_region
|
| 314 |
|
|
ehr_next (eh_region r, eh_region start)
|
| 315 |
|
|
{
|
| 316 |
|
|
if (r->inner)
|
| 317 |
|
|
r = r->inner;
|
| 318 |
|
|
else if (r->next_peer && r != start)
|
| 319 |
|
|
r = r->next_peer;
|
| 320 |
|
|
else
|
| 321 |
|
|
{
|
| 322 |
|
|
do
|
| 323 |
|
|
{
|
| 324 |
|
|
r = r->outer;
|
| 325 |
|
|
if (r == start)
|
| 326 |
|
|
return NULL;
|
| 327 |
|
|
}
|
| 328 |
|
|
while (r->next_peer == NULL);
|
| 329 |
|
|
r = r->next_peer;
|
| 330 |
|
|
}
|
| 331 |
|
|
return r;
|
| 332 |
|
|
}
|
| 333 |
|
|
|
| 334 |
|
|
#define FOR_ALL_EH_REGION_AT(R, START) \
|
| 335 |
|
|
for ((R) = (START); (R) != NULL; (R) = ehr_next (R, START))
|
| 336 |
|
|
|
| 337 |
|
|
#define FOR_ALL_EH_REGION_FN(R, FN) \
|
| 338 |
|
|
for ((R) = (FN)->eh->region_tree; (R) != NULL; (R) = ehr_next (R, NULL))
|
| 339 |
|
|
|
| 340 |
|
|
#define FOR_ALL_EH_REGION(R) FOR_ALL_EH_REGION_FN (R, cfun)
|