Commit 9a0d1e1b by Andrew MacLeod Committed by Andrew Macleod

First cut of changes to utilize the new exception handling model

From-SVN: r19746
parent 2129b081
Thu May 14 16:30:47 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
* eh-common.h: New file for basic EH data structures.
* except.h: Various prototypes and structures for NEW_EH_MODEL
* function.h (struct function): Add a struct eh_stack for the catch
clause stack.
* except.c (gen_exception_label): New function to generate an
exception label.
(push_eh_entry): Use gen_exception_label() and init 'label_used' field.
(push_entry): New function to push an existing entry onto a stack.
(receive_exception_label): New function to emit the code required
at the start of all catch blocks.
(struct func_eh_entry): New structure for maintaining handlers
associated with EH regions.
(new_eh_region_entry): New function to register an EH region.
(add_new_handler): New function to register a handler with a region.
(get_new_handler): Creates anew handler entry for registering.
(find_func_region): New function to convert a NOTE eh region number
to an Eh region index.
(get_first_handler): New function to get the first handler in a region.
(clear_function_eh_region): New function to release memory.
(duplicate_handlers): New function to duplicate a list of handlers.
(expand_eh_region_end): Create a new region entry node as well.
(expand_leftover_cleanups): Call receive_exception_label() and
register the cleanup as a handler to the current region.
(expand_start_catch): New function to start a catch clause.
(expand_end_catch): New function to end a catch clause.
(expand_start_all_catch): restructure to not do the equivilent of
what expand_start_catch() does now. Push the exception region being
handled onto the catch stack.
(output_exception_table_entry): Issue an entry for each handler
associated with a region.
(set_exception_lang_code): New function for setting the language code.
(set_exception_version_code): New function to set the version number.
(output_exception_table): Output version and language codes.
(find_exception_handler_labels): Find handler labels using new scheme.
(is_exception_handler_label): New function, returns 1 if label is
present as a handler in some exception region.
(check_exception_handler_labels): Use the new scheme.
(init_eh_for_function): Initialize the catch stack.
(save_eh_status): Save the catch stack.
(restore_eh_status): Restore the catch stack.
(scan_region): Don't remove unreferenced handler label. Flow does it.
(get_reg_for_handler): New function to get the eh_context pointer
passed by __throw.
(expand_builtin_eh_stub): Changes required for NEW_EH_MODEL only.
* final.c (final_scan_insn): With NEW_EH_MODEL, add EH table
entry when processing END region rather that START region.
* flow.c (find_basic_blocks_1): Find all potential handler regions
now that we don't automatically know what the labels might be.
Let scan_region() remove unreferenced EH BEGIN/END labels.
* integrate.c (get_label_from_map): Put inlined labels onto the
permanent obstack since we dont know which ones might be exception
labels.
(save_for_inline_copying): Make new copies of all the handlers.
(expand_inline_function): Make new copies of all the handlers.
* libgcc2.c: Remove local struct decls, and include eh-common.h.
(find_exception_handler): With NEW_EH_MODEL the first matching
region we find is the right one. Add eh_info as a new parameter.
(__throw): Pass eh_info to find_exception_handler. Set handler
and pass use different regs under NEW_EH_MODEL.
Thu May 14 12:58:21 1998 Jim Wilson <wilson@cygnus.com>
* i960.h (hard_regno_mode_ok): Changed to function from array of
......
Thu May 14 16:30:47 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
* exception.cc: Include eh-common.h.
(struct cp_eh_info): add eh_info struct with NEW_EH_MODEL.
(__cplus_type_matcher): First stab at new C++ runtime type matcher.
(__cp_push_exception): Initialize eh_info struct as well.
* except.c: Remove local structs and include eh-common.h.
(init_exception_processing): Set language and version codes.
(call_eh_info): add presence of eh_info to runtime description of
struct cp_eh_info.
(expand_end_eh_spec): call start_catch_block() and end_catch_block().
* semantics.c (finish_try_block): call start_catch_block() and
end_catch_block().
* parse.y (function_try_block): call start_catch_block() and
end_catch_block().
Thu May 14 12:27:34 1998 Brendan Kehoe <brendan@cygnus.com>
* typeck.c (original_type): New function.
......
......@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA. */
#include "function.h"
#include "defaults.h"
#include "toplev.h"
#include "eh-common.h"
rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
......@@ -66,14 +67,6 @@ static tree do_pop_exception PROTO((void));
#endif
#ifdef EXCEPT_SECTION_ASM_OP
typedef struct {
void *start_region;
void *end_region;
void *exception_handler;
} exception_table;
#endif /* EXCEPT_SECTION_ASM_OP */
#ifdef EXCEPT_SECTION_ASM_OP
/* on machines which support it, the exception table lives in another section,
but it needs a label so we can reference it... This sets up that
......@@ -227,6 +220,11 @@ init_exception_processing ()
push_lang_context (lang_name_c);
#ifdef NEW_EH_MODEL
set_exception_lang_code (EH_LANG_C_plus_plus);
set_exception_version_code (1);
#endif
CatchMatch
= builtin_function (flag_rtti
? "__throw_type_match_rtti"
......@@ -269,7 +267,8 @@ call_eh_info ()
fn = IDENTIFIER_GLOBAL_VALUE (fn);
else
{
tree t, fields[6];
tree t1,t, fields[7];
int fo = 0;
/* Declare cp_eh_info * __cp_exception_info (void),
as defined in exception.cc. */
......@@ -278,25 +277,56 @@ call_eh_info ()
/* struct cp_eh_info. This must match exception.cc. Note that this
type is not pushed anywhere. */
#ifdef NEW_EH_MODEL
t1= make_lang_type (RECORD_TYPE);
fields[0] = build_lang_field_decl (FIELD_DECL,
get_identifier ("handler_label"), ptr_type_node);
fields[1] = build_lang_field_decl (FIELD_DECL,
get_identifier ("dynamic_handler_chain"), ptr_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL,
get_identifier ("info"), ptr_type_node);
/* N.B.: The fourth field LEN is expected to be
the number of fields - 1, not the total number of fields. */
finish_builtin_type (t1, "eh_context", fields, 2, ptr_type_node);
t1 = build_pointer_type (t1);
t1= make_lang_type (RECORD_TYPE);
fields[0] = build_lang_field_decl (FIELD_DECL,
get_identifier ("match_function"), ptr_type_node);
fields[1] = build_lang_field_decl (FIELD_DECL,
get_identifier ("coerced_value"), ptr_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL,
get_identifier ("language"), short_integer_type_node);
fields[3] = build_lang_field_decl (FIELD_DECL,
get_identifier ("version"), short_integer_type_node);
/* N.B.: The fourth field LEN is expected to be
the number of fields - 1, not the total number of fields. */
finish_builtin_type (t1, "__eh_info", fields, 3, ptr_type_node);
fo = 1;
#endif
t = make_lang_type (RECORD_TYPE);
fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("value"),
#ifdef NEW_EH_MODEL
fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("eh_info"),
t1);
#endif
fields[0+fo] = build_lang_field_decl (FIELD_DECL, get_identifier ("value"),
ptr_type_node);
fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
fields[1+fo] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
ptr_type_node);
fields[2] = build_lang_field_decl
fields[2+fo] = build_lang_field_decl
(FIELD_DECL, get_identifier ("cleanup"),
build_pointer_type (build_function_type
(ptr_type_node, tree_cons
(NULL_TREE, ptr_type_node, void_list_node))));
fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("caught"),
fields[3+fo] = build_lang_field_decl (FIELD_DECL, get_identifier ("caught"),
boolean_type_node);
fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("next"),
fields[4+fo] = build_lang_field_decl (FIELD_DECL, get_identifier ("next"),
build_pointer_type (t));
fields[5] = build_lang_field_decl
fields[5+fo] = build_lang_field_decl
(FIELD_DECL, get_identifier ("handlers"), long_integer_type_node);
/* N.B.: The fourth field LEN is expected to be
the number of fields - 1, not the total number of fields. */
finish_builtin_type (t, "cp_eh_info", fields, 5, ptr_type_node);
finish_builtin_type (t, "cp_eh_info", fields, 5+fo, ptr_type_node);
t = build_pointer_type (t);
/* And now the function. */
......@@ -681,6 +711,7 @@ expand_end_eh_spec (raises)
int count = 0;
expand_start_all_catch ();
expand_start_catch (NULL);
expand_start_catch_block (NULL_TREE, NULL_TREE);
/* Build up an array of type_infos. */
......@@ -733,6 +764,7 @@ expand_end_eh_spec (raises)
expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
expand_end_catch_block ();
expand_end_catch ();
expand_end_all_catch ();
}
......
......@@ -30,6 +30,7 @@
#include "typeinfo"
#include "exception"
#include <stddef.h>
#include "eh-common.h"
/* Define terminate, unexpected, set_terminate, set_unexpected as
well as the default terminate func and default unexpected func. */
......@@ -85,6 +86,9 @@ std::unexpected ()
struct cp_eh_info
{
#ifdef NEW_EH_MODEL
__eh_info eh_info;
#endif
void *value;
void *type;
void (*cleanup)(void *, int);
......@@ -133,6 +137,29 @@ __eh_free (void *p)
free (p);
}
#ifdef NEW_EH_MODEL
typedef void * (* rtimetype) (void);
extern "C" void *
__cplus_type_matcher (cp_eh_info *info, exception_table *matching_info,
exception_descriptor *exception_table)
{
void *ret;
if (exception_table->lang.language != EH_LANG_C_plus_plus)
return NULL;
/* we don't worry about version info yet, there is only one version! */
void *match_type = ((rtimetype) (matching_info->match_info)) ();
ret = __throw_type_match_rtti (match_type, info->type, info->value);
return ret;
}
#endif
/* Compiler hook to push a new exception onto the stack.
Used by expand_throw(). */
......@@ -147,6 +174,13 @@ __cp_push_exception (void *value, void *type, void (*cleanup)(void *, int))
p->handlers = 0;
p->caught = false;
#ifdef NEW_EH_MODEL
p->eh_info.match_function = __cplus_type_matcher;
p->eh_info.language = EH_LANG_C_plus_plus;
p->eh_info.version = 1;
p->eh_info.coerced_value = NULL;
#endif
cp_eh_info **q = __get_eh_info ();
p->next = *q;
......
......@@ -3222,12 +3222,16 @@ function_try_block:
expand_start_early_try_stmts ();
}
ctor_initializer_opt compstmt
{ expand_start_all_catch (); }
{
expand_start_all_catch ();
expand_start_catch (NULL);
}
handler_seq
{
int nested = (hack_decl_function_context
(current_function_decl) != NULL_TREE);
expand_end_all_catch ();
expand_end_catch ();
finish_function (lineno, (int)$3, nested);
}
;
......
......@@ -587,7 +587,10 @@ finish_try_block (try_block)
if (processing_template_decl)
RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
else
expand_start_all_catch ();
{
expand_start_all_catch ();
expand_start_catch (NULL);
}
}
/* Finish a handler-sequence for a try-block, which may be given by
......@@ -600,7 +603,10 @@ finish_handler_sequence (try_block)
if (processing_template_decl)
RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
else
expand_end_all_catch ();
{
expand_end_catch ();
expand_end_all_catch ();
}
}
/* Begin a handler. Returns a HANDLER if appropriate. */
......
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of GNU CC. */
/* This file contains the structures required for the language
independant exception handling model. Both the static compiler and
the runtime library share this file. */
/* The compiler flag NEW_EH_MODEL is used to determine whether the
compiler supports the new runtime typechecking mechanism or not. Under
the new model, runtime info is contained in the exception table, and
the __throw() library routine determines which handler to call based
on the results of a call to a matching function provided by the expcetion
thrower. Otherwise the old scheme of calling any handler which matches
an exception range is used, and the handler is responsible for all
checking of runtime conditions. If the handler wasn't suppose to
get the exception, it performs a re-throw. */
#include "gansidecl.h"
#ifndef NEW_EH_MODEL
struct eh_context
{
void **dynamic_handler_chain;
/* This is language dependent part of the eh context. */
void *info;
};
#else
/* The handler_label field MUST be the first field in this structure. The
__throw() library routine expects uses __eh_stub() from except.c, which
simply dereferences the context pointer to get the handler */
struct eh_context
{
void *handler_label;
void **dynamic_handler_chain;
/* This is language dependent part of the eh context. */
void *info;
};
#endif
#ifndef EH_TABLE_LOOKUP
#ifndef NEW_EH_MODEL
typedef struct exception_table
{
void *start_region;
void *end_region;
void *exception_handler;
} exception_table;
typedef exception_table exception_descriptor;
#else
typedef struct exception_table
{
void *start_region;
void *end_region;
void *exception_handler;
void *match_info; /* runtime type info */
} exception_table;
/* The language identifying portion of an exception table */
typedef struct exception_lang_info
{
short language;
short version;
} exception_lang_info;
/* Each function has an exception_descriptor which contains the
language info, and a table of exception ranges and handlers */
typedef struct exception_descriptor
{
exception_lang_info lang;
exception_table table[1];
} exception_descriptor;
/* A pointer to a matching function is initialized at runtime by the
specific language if run-time exceptions are supported.
The function takes 3 parameters
1 - runtime exception that has been thrown info. (__eh_info *)
2 - Match info pointer from the region being considered (void *)
3 - exception table region is in (exception descriptor *)
*/
typedef void * (*__eh_matcher) PROTO ((void *, void *, void *));
/* This is the runtime exception information. This forms the minimum required
information for an exception info pointer in an eh_context structure. */
typedef struct __eh_info
{
__eh_matcher match_function;
void *coerced_value;
short language;
short version;
} __eh_info;
/* Convienient language codes for ID the originating language. Similar
to the codes in dwarf2.h. */
enum exception_source_language
{
EH_LANG_C89 = 0x0001,
EH_LANG_C = 0x0002,
EH_LANG_Ada83 = 0x0003,
EH_LANG_C_plus_plus = 0x0004,
EH_LANG_Cobol74 = 0x0005,
EH_LANG_Cobol85 = 0x0006,
EH_LANG_Fortran77 = 0x0007,
EH_LANG_Fortran90 = 0x0008,
EH_LANG_Pascal83 = 0x0009,
EH_LANG_Modula2 = 0x000a,
EH_LANG_Java = 0x000b,
EH_LANG_Mips_Assembler = 0x8001
};
#endif
#endif /* EH_TABLE_LOOKUP */
......@@ -43,6 +43,10 @@ struct label_node {
EXCEPTION_HANDLER_LABEL is the label corresponding to the handler
for this region.
LABEL_USED indicates whether a CATCH block has already used this
label or not. New ones are needed for additional catch blocks if
it has.
FINALIZATION is the tree codes for the handler, or is NULL_TREE if
one hasn't been generated yet, or is integer_zero_node to mark the
end of a group of try blocks. */
......@@ -50,8 +54,8 @@ struct label_node {
struct eh_entry {
rtx outer_context;
rtx exception_handler_label;
tree finalization;
int label_used;
};
/* A list of EH_ENTRYs. ENTRY is the entry; CHAIN points to the next
......@@ -145,17 +149,89 @@ extern int doing_eh PROTO ((int));
/* Toplevel initialization for EH. */
#ifdef NEW_EH_MODEL
void set_exception_lang_code PROTO((short));
void set_exception_version_code PROTO((short));
#endif
/* A list of handlers asocciated with an exception region. HANDLER_LABEL
is the the label that control should be transfered to if the data
in TYPE_INFO matches an exception. a value of NULL_TREE for TYPE_INFO
means This is a cleanup, and must always be called. A value of
CATCH_ALL_TYPE works like a cleanup, but a call to the runtime matcher
is still performed to avoid being caught by a different language
exception. NEXT is a pointer to the next handler for this region.
NULL means there are no more. */
#define CATCH_ALL_TYPE (tree *) -1
typedef struct handler_info
{
rtx handler_label;
void *type_info;
struct handler_info *next;
} handler_info;
/* Add a new eh_entry for this function, The parameter specifies what
exception region number NOTE insns use to delimit this range.
The integer returned is uniquely identifies this exception range
within an internal table. */
int new_eh_region_entry PROTO((int));
/* Add new handler information to an exception range. The first parameter
specifies the range number (returned from new_eh_entry()). The second
parameter specifies the handler. By default the handler is inserted at
the end of the list. A handler list may contain only ONE NULL_TREE
typeinfo entry. Regardless where it is positioned, a NULL_TREE entry
is always output as the LAST handler in the exception table for a region. */
void add_new_handler PROTO((int, struct handler_info *));
/* Create a new handler structure initialized with the handler label and
typeinfo fields passed in. */
struct handler_info *get_new_handler PROTO((rtx, void *));
/* Make a duplicate of an exception region by copying all the handlers
for an exception region. Return the new handler index. */
int duplicate_handlers PROTO((int, int));
/* Get a pointer to the first handler in an exception region's list. */
struct handler_info *get_first_handler PROTO((int));
extern void init_eh PROTO((void));
/* Initialization for the per-function EH data. */
extern void init_eh_for_function PROTO((void));
/* Generate an exception label. Use instead of gen_label_rtx */
extern rtx gen_exception_label PROTO((void));
/* Adds an EH table entry for EH entry number N. Called from
final_scan_insn for NOTE_INSN_EH_REGION_BEG. */
extern void add_eh_table_entry PROTO((int n));
/* Start a catch clause, triggered by runtime value paramter. */
#ifdef TREE_CODE
extern void expand_start_catch PROTO((tree));
#endif
/* End a catch clause. */
extern void expand_end_catch PROTO((void));
/* Returns a non-zero value if we need to output an exception table. */
extern int exception_table_p PROTO((void));
......@@ -225,6 +301,10 @@ extern void end_eh_unwinder PROTO((void));
extern void find_exception_handler_labels PROTO((void));
/* Determine if an arbitrary label is an exception label */
extern int is_exception_handler_label PROTO((int));
/* Performs sanity checking on the check_exception_handler_labels
list. */
......
......@@ -1988,7 +1988,9 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
&& ! exceptions_via_longjmp)
{
ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", NOTE_BLOCK_NUMBER (insn));
#ifndef NEW_EH_MODEL
add_eh_table_entry (NOTE_BLOCK_NUMBER (insn));
#endif
#ifdef ASM_OUTPUT_EH_REGION_BEG
ASM_OUTPUT_EH_REGION_BEG (file, NOTE_BLOCK_NUMBER (insn));
#endif
......@@ -1999,6 +2001,9 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
&& ! exceptions_via_longjmp)
{
ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", NOTE_BLOCK_NUMBER (insn));
#ifdef NEW_EH_MODEL
add_eh_table_entry (NOTE_BLOCK_NUMBER (insn));
#endif
#ifdef ASM_OUTPUT_EH_REGION_END
ASM_OUTPUT_EH_REGION_END (file, NOTE_BLOCK_NUMBER (insn));
#endif
......
......@@ -396,7 +396,8 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
register char *block_marked = (char *) alloca (n_basic_blocks);
/* An array of CODE_LABELs, indexed by UID for the start of the active
EH handler for each insn in F. */
rtx *active_eh_handler;
int *active_eh_region;
int *nested_eh_region;
/* List of label_refs to all labels whose addresses are taken
and used as data. */
rtx label_value_list;
......@@ -406,7 +407,8 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
int in_libcall_block = 0;
pass = 1;
active_eh_handler = (rtx *) alloca ((max_uid_for_flow + 1) * sizeof (rtx));
active_eh_region = (int *) alloca ((max_uid_for_flow + 1) * sizeof (int));
nested_eh_region = (int *) alloca ((max_label_num () + 1) * sizeof (int));
restart:
label_value_list = 0;
......@@ -414,7 +416,8 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
bzero (block_live, n_basic_blocks);
bzero (block_marked, n_basic_blocks);
bzero (basic_block_computed_jump_target, n_basic_blocks);
bzero ((char *) active_eh_handler, (max_uid_for_flow + 1) * sizeof (rtx));
bzero ((char *) active_eh_region, (max_uid_for_flow + 1) * sizeof (int));
bzero ((char *) nested_eh_region, (max_label_num () + 1) * sizeof (int));
current_function_has_computed_jump = 0;
/* Initialize with just block 0 reachable and no blocks marked. */
......@@ -482,20 +485,18 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
label_value_list);
}
/* Keep a lifo list of the currently active exception handlers. */
/* Keep a lifo list of the currently active exception notes. */
if (GET_CODE (insn) == NOTE)
{
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
{
for (x = exception_handler_labels; x; x = XEXP (x, 1))
if (CODE_LABEL_NUMBER (XEXP (x, 0)) == NOTE_BLOCK_NUMBER (insn))
{
eh_note = gen_rtx_EXPR_LIST (VOIDmode,
XEXP (x, 0), eh_note);
break;
}
if (x == NULL_RTX)
abort ();
if (eh_note)
nested_eh_region [NOTE_BLOCK_NUMBER (insn)] =
NOTE_BLOCK_NUMBER (XEXP (eh_note, 0));
else
nested_eh_region [NOTE_BLOCK_NUMBER (insn)] = 0;
eh_note = gen_rtx_EXPR_LIST (VOIDmode,
insn, eh_note);
}
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
eh_note = XEXP (eh_note, 1);
......@@ -509,8 +510,8 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
&& (asynchronous_exceptions
|| (GET_CODE (insn) == CALL_INSN
&& ! in_libcall_block)))
active_eh_handler[INSN_UID (insn)] = XEXP (eh_note, 0);
active_eh_region[INSN_UID (insn)] =
NOTE_BLOCK_NUMBER (XEXP (eh_note, 0));
BLOCK_NUM (insn) = i;
if (code != NOTE)
......@@ -655,11 +656,20 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
&& ! find_reg_note (insn, REG_RETVAL,
NULL_RTX)))
{
if (active_eh_handler[INSN_UID (insn)])
mark_label_ref (gen_rtx_LABEL_REF (VOIDmode,
active_eh_handler[INSN_UID (insn)]),
insn, 0);
if (active_eh_region[INSN_UID (insn)])
{
int region;
handler_info *ptr;
region = active_eh_region[INSN_UID (insn)];
for ( ; region;
region = nested_eh_region[region])
{
ptr = get_first_handler (region);
for ( ; ptr ; ptr = ptr->next)
mark_label_ref (gen_rtx_LABEL_REF
(VOIDmode, ptr->handler_label), insn, 0);
}
}
if (!asynchronous_exceptions)
{
for (x = nonlocal_label_list;
......@@ -764,6 +774,10 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
/* Now we have to find the EH_BEG and EH_END notes
associated with this label and remove them. */
#if 0
/* Handlers and labels no longer needs to have the same values.
If there are no references, scan_region will remove any region
labels which are of no use. */
for (x = get_insns (); x; x = NEXT_INSN (x))
{
if (GET_CODE (x) == NOTE
......@@ -778,6 +792,7 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
NOTE_SOURCE_FILE (x) = 0;
}
}
#endif
break;
}
prev = &XEXP (x, 1);
......
......@@ -133,6 +133,7 @@ struct function
/* For exception handling information. */
struct eh_stack ehstack;
struct eh_stack catchstack;
struct eh_queue ehqueue;
rtx catch_clauses;
struct label_node *false_label_stack;
......
......@@ -95,7 +95,12 @@ get_label_from_map (map, i)
rtx x = map->label_map[i];
if (x == NULL_RTX)
x = map->label_map[i] = gen_label_rtx();
{
push_obstacks_nochange ();
end_temporary_allocation ();
x = map->label_map[i] = gen_label_rtx();
pop_obstacks ();
}
return x;
}
......@@ -658,10 +663,28 @@ save_for_inline_copying (fndecl)
if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG
|| NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_END)
{
int new_region = CODE_LABEL_NUMBER
(label_map[NOTE_BLOCK_NUMBER (copy)]);
/* we have to duplicate the handlers for the original */
if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG)
{
handler_info *ptr, *temp;
int nr;
nr = new_eh_region_entry (new_region);
ptr = get_first_handler (NOTE_BLOCK_NUMBER (copy));
for ( ; ptr; ptr = ptr->next)
{
temp = get_new_handler (
label_map[CODE_LABEL_NUMBER (ptr->handler_label)],
ptr->type_info);
add_new_handler (nr, temp);
}
}
/* We have to forward these both to match the new exception
region. */
NOTE_BLOCK_NUMBER (copy)
= CODE_LABEL_NUMBER (label_map[NOTE_BLOCK_NUMBER (copy)]);
NOTE_BLOCK_NUMBER (copy) = new_region;
}
RTX_INTEGRATED_P (copy) = RTX_INTEGRATED_P (insn);
......@@ -2038,6 +2061,22 @@ expand_inline_function (fndecl, parms, target, ignore, type,
rtx label
= get_label_from_map (map, NOTE_BLOCK_NUMBER (copy));
/* we have to duplicate the handlers for the original */
if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG)
{
handler_info *ptr, *temp;
int nr;
nr = new_eh_region_entry (CODE_LABEL_NUMBER (label));
ptr = get_first_handler (NOTE_BLOCK_NUMBER (copy));
for ( ; ptr; ptr = ptr->next)
{
temp = get_new_handler ( get_label_from_map (map,
CODE_LABEL_NUMBER (ptr->handler_label)),
ptr->type_info);
add_new_handler (nr, temp);
}
}
/* We have to forward these both to match the new exception
region. */
NOTE_BLOCK_NUMBER (copy) = CODE_LABEL_NUMBER (label);
......
......@@ -3046,14 +3046,10 @@ __empty ()
{
}
/* EH context structure. */
struct eh_context
{
void **dynamic_handler_chain;
/* This is language dependent part of the eh context. */
void *info;
};
/* Include definitions of EH context and table layout */
#include "eh-common.h"
/* This is a safeguard for dynamic handler chain. */
......@@ -3361,11 +3357,6 @@ EH_TABLE_LOOKUP
#else
#ifdef DWARF2_UNWIND_INFO
typedef struct exception_table {
void *start;
void *end;
void *exception_handler;
} exception_table;
/* This routine takes a PC and a pointer to the exception region TABLE for
its translation unit, and returns the address of the exception handler
......@@ -3376,31 +3367,68 @@ typedef struct exception_table {
an inner block. */
static void *
find_exception_handler (void *pc, exception_table *table)
find_exception_handler (void *pc, exception_descriptor *table, void *eh_info)
{
if (table)
{
#ifdef NEW_EH_MODEL
/* The new model assumed the table is sorted inner-most out so the
first region we find which matches is the correct one */
int pos;
void *ret;
exception_table *tab = &(table->table[0]);
/* Subtract 1 from the PC to avoid hitting the next region */
pc--;
/* We can't do a binary search because the table is in inner-most
to outermost address ranges within functions */
for (pos = 0; tab[pos].start_region != (void *) -1; pos++)
{
if (tab[pos].start_region <= pc && tab[pos].end_region > pc)
{
if (tab[pos].match_info)
{
__eh_matcher matcher = ((__eh_info *)eh_info)->match_function;
/* match info but no matcher is NOT a match */
if (matcher)
{
ret = (*matcher)(eh_info, tab[pos].match_info, table);
if (ret)
{
((__eh_info *)eh_info)->coerced_value = ret;
return tab[pos].exception_handler;
}
}
}
else
return tab[pos].exception_handler;
}
}
#else
int pos;
int best = -1;
/* We can't do a binary search because the table isn't guaranteed
to be sorted from function to function. */
for (pos = 0; table[pos].exception_handler != (void *) -1; ++pos)
{
if (table[pos].start <= pc && table[pos].end > pc)
{
/* This can apply. Make sure it is at least as small as
the previous best. */
if (best == -1 || (table[pos].end <= table[best].end
&& table[pos].start >= table[best].start))
best = pos;
}
/* But it is sorted by starting PC within a function. */
else if (best >= 0 && table[pos].start > pc)
break;
}
to be sorted from function to function. */
for (pos = 0; table[pos].start_region != (void *) -1; ++pos)
{
if (table[pos].start_region <= pc && table[pos].end_region > pc)
{
/* This can apply. Make sure it is at least as small as
the previous best. */
if (best == -1 || (table[pos].end_region <= table[best].end_region
&& table[pos].start_region >= table[best].start_region))
best = pos;
}
/* But it is sorted by starting PC within a function. */
else if (best >= 0 && table[pos].start_region > pc)
break;
}
if (best != -1)
return table[best].exception_handler;
return table[best].exception_handler;
#endif
}
return (void *) 0;
......@@ -3583,7 +3611,7 @@ label:
if (! udata)
break;
handler = find_exception_handler (pc, udata->eh_ptr);
handler = find_exception_handler (pc, udata->eh_ptr, eh->info);
/* If we found one, we can stop searching. */
if (handler)
......@@ -3602,6 +3630,10 @@ label:
if (! handler)
__terminate ();
#ifdef NEW_EH_MODEL
eh->handler_label = handler;
#endif
if (pc == saved_pc)
/* We found a handler in the throw context, no need to unwind. */
udata = my_udata;
......@@ -3669,7 +3701,13 @@ label:
/* Set up the registers we use to communicate with the stub.
We check STACK_GROWS_DOWNWARD so the stub can use adjust_stack. */
#ifdef NEW_EH_MODEL
__builtin_set_eh_regs ((void *)eh,
#else
__builtin_set_eh_regs (handler,
#endif
#ifdef STACK_GROWS_DOWNWARD
udata->cfa - my_udata->cfa
#else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment