aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrew MacLeod <amacleod@cygnus.com>1998-06-23 07:10:29 +0000
committerAndrew Macleod <amacleod@gcc.gnu.org>1998-06-23 07:10:29 +0000
commit5816cb14dd6c7d682888a0cdd52a73e0867edd05 (patch)
treecaff48e4d357cdb27c61741d2e59101bb1bba09b /gcc
parent83de03dfd8d9c845da0d3370839dbf1518c48f52 (diff)
downloadgcc-5816cb14dd6c7d682888a0cdd52a73e0867edd05.zip
gcc-5816cb14dd6c7d682888a0cdd52a73e0867edd05.tar.gz
gcc-5816cb14dd6c7d682888a0cdd52a73e0867edd05.tar.bz2
Have -fnew-exceptions actually use the runtime field, and not generate runtime checking code inside each handler.
Have -fnew-exceptions actually use the runtime field, and not generate runtime checking code inside each handler. THis works at low opt, but not with optimization at the moment. Tue Jun 23 10:06:07 EDT 1998 Andrew MacLeod (amacleod@cygnus.com) * eh-common.h (struct __eh_info): Remove coerced value field. * libgcc2.c (find_exception_handler): Don't set coerced_value field. * except.c (get_dynamic_handler_chain, get_dynamic_cleanup_chain): Use POINTER_SIZE instead of Pmode. (expand_start_all_catch): Call start_catch_handler() if we are not using new style exceptions. 1998-06-22 Andrew MacLeod (amacleod@cygnus.com) * parse.y (function_try_block): Don't call start_catch_handler. * except.c (call_eh_info): Remove coerced field from declaration. (build_eh_type_type_ref): New function to create an address of a rtti function for the new style exception tables. (expand_start_catch_block): Split function, this contains the common part. (process_start_catch_block_old): New function to perform the rest of expand_start_catch_block under old style exceptions. (process_start_catch_block_old): New function to perform the rest of expand_start_catch_block under new style exceptions. (expand_end_catch_block): Only pop the false label off the stack under the old style of exceptions. * semantics.c (finish_try_block): Don't call start_catch_handler. * exception.cc (struct cp_eh_info): Add original_value field. (__cplus_type_matcher): Perform type matching on the original exception value, and if we have a match, set the current value. (__cp_push_exception): Set the original expcetion value. From-SVN: r20671
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/cp/ChangeLog20
-rw-r--r--gcc/cp/except.c185
-rw-r--r--gcc/cp/exception.cc8
-rw-r--r--gcc/cp/parse.y1
-rw-r--r--gcc/cp/semantics.c1
-rw-r--r--gcc/eh-common.h1
-rw-r--r--gcc/except.c8
-rw-r--r--gcc/libgcc2.c5
9 files changed, 217 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 69b80ca..d4f3d45 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+Tue Jun 23 10:06:07 EDT 1998 Andrew MacLeod (amacleod@cygnus.com)
+
+ * eh-common.h (struct __eh_info): Remove coerced value field.
+ * libgcc2.c (find_exception_handler): Don't set coerced_value field.
+ * except.c (get_dynamic_handler_chain, get_dynamic_cleanup_chain): Use
+ POINTER_SIZE instead of Pmode.
+ (expand_start_all_catch): Call start_catch_handler() if we are not
+ using new style exceptions.
+
Tue Jun 23 06:45:00 1998 Catherine Moore <clm@cygnus.com>
* varasm.c (assemble_variable): Remove reference to warn_bss_align.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 27a8178..ddd56db7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,23 @@
+1998-06-23 Andrew MacLeod (amacleod@cygnus.com)
+
+ * parse.y (function_try_block): Don't call start_catch_handler.
+ * except.c (call_eh_info): Remove coerced field from declaration.
+ (build_eh_type_type_ref): New function to create an address of a
+ rtti function for the new style exception tables.
+ (expand_start_catch_block): Split function, this contains the
+ common part.
+ (process_start_catch_block_old): New function to perform the rest
+ of expand_start_catch_block under old style exceptions.
+ (process_start_catch_block_old): New function to perform the rest
+ of expand_start_catch_block under new style exceptions.
+ (expand_end_catch_block): Only pop the false label off the stack under
+ the old style of exceptions.
+ * semantics.c (finish_try_block): Don't call start_catch_handler.
+ * exception.cc (struct cp_eh_info): Add original_value field.
+ (__cplus_type_matcher): Perform type matching on the original exception
+ value, and if we have a match, set the current value.
+ (__cp_push_exception): Set the original expcetion value.
+
1998-06-23 Jason Merrill <jason@yorick.cygnus.com>
* call.c (joust): Fix confusing conversion warning.
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index dba0f09..438351e 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -56,6 +56,9 @@ static tree get_eh_type PROTO((void));
static tree get_eh_caught PROTO((void));
static tree get_eh_handlers PROTO((void));
static tree do_pop_exception PROTO((void));
+static void process_start_catch_block PROTO((tree, tree));
+static void process_start_catch_block_old PROTO((tree, tree));
+static tree build_eh_type_type_ref PROTO((tree));
#if 0
/* This is the startup, and finish stuff per exception table. */
@@ -273,14 +276,12 @@ call_eh_info ()
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,
+ fields[2] = 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);
+ finish_builtin_type (t1, "__eh_info", fields, 2, ptr_type_node);
t = make_lang_type (RECORD_TYPE);
fields[0] = build_lang_field_decl (FIELD_DECL,
get_identifier ("eh_info"), t1);
@@ -414,6 +415,48 @@ build_eh_type_type (type)
return build1 (ADDR_EXPR, ptr_type_node, exp);
}
+/* Build the address of a runtime type for use in the runtime matching
+ field of the new exception model */
+
+static tree
+build_eh_type_type_ref (type)
+ tree type;
+{
+ char *typestring;
+ tree exp;
+ int susp;
+
+ if (type == error_mark_node)
+ return error_mark_node;
+
+ /* peel back references, so they match. */
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+
+ /* Peel off cv qualifiers. */
+ type = TYPE_MAIN_VARIANT (type);
+
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+
+ if (flag_rtti)
+ {
+ exp = get_tinfo_fn (type);
+ TREE_USED (exp) = 1;
+ mark_inline_for_output (exp);
+ exp = build1 (ADDR_EXPR, ptr_type_node, exp);
+ }
+ else
+ {
+ typestring = build_overload_name (type, 1, 1);
+ exp = combine_strings (build_string (strlen (typestring)+1, typestring));
+ exp = build1 (ADDR_EXPR, ptr_type_node, exp);
+ }
+ pop_obstacks ();
+ return (exp);
+}
+
+
/* Build a type value for use at runtime for a exp that is thrown or
matched against by the exception handling system. */
@@ -495,7 +538,7 @@ build_terminate_handler ()
return term;
}
-/* call this to start a catch block. Typename is the typename, and identifier
+/* Call this to start a catch block. Typename is the typename, and identifier
is the variable to place the object in or NULL if the variable doesn't
matter. If typename is NULL, that means its a "catch (...)" or catch
everything. In that case we don't need to do any type checking.
@@ -505,9 +548,7 @@ void
expand_start_catch_block (declspecs, declarator)
tree declspecs, declarator;
{
- rtx false_label_rtx;
- tree decl = NULL_TREE;
- tree init;
+ tree decl;
if (processing_template_decl)
{
@@ -527,6 +568,25 @@ expand_start_catch_block (declspecs, declarator)
if (! doing_eh (1))
return;
+ if (flag_new_exceptions)
+ process_start_catch_block (declspecs, declarator);
+ else
+ process_start_catch_block_old (declspecs, declarator);
+}
+
+
+/* This function performs the expand_start_catch_block functionality for
+ exceptions implemented in the old style, where catch blocks were all
+ called, and had to check the runtime information themselves. */
+
+static void
+process_start_catch_block_old (declspecs, declarator)
+ tree declspecs, declarator;
+{
+ rtx false_label_rtx;
+ tree decl = NULL_TREE;
+ tree init;
+
/* Create a binding level for the eh_info and the exception object
cleanup. */
pushlevel (0);
@@ -631,6 +691,111 @@ expand_start_catch_block (declspecs, declarator)
emit_line_note (input_filename, lineno);
}
+/* This function performs the expand_start_catch_block functionality for
+ exceptions implemented in the new style. __throw determines whether
+ a handler needs to be called or not, so the handler itself has to do
+ nothing additionaal. */
+
+static void
+process_start_catch_block (declspecs, declarator)
+ tree declspecs, declarator;
+{
+ rtx false_label_rtx;
+ tree decl = NULL_TREE;
+ tree init;
+
+ /* Create a binding level for the eh_info and the exception object
+ cleanup. */
+ pushlevel (0);
+ expand_start_bindings (0);
+
+
+ if (declspecs)
+ {
+ decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
+
+ if (decl == NULL_TREE)
+ error ("invalid catch parameter");
+ }
+
+ if (decl)
+ start_catch_handler (build_eh_type_type_ref (TREE_TYPE (decl)));
+ else
+ start_catch_handler (NULL_TREE);
+
+ emit_line_note (input_filename, lineno);
+
+ push_eh_info ();
+
+ if (decl)
+ {
+ tree exp;
+ rtx call_rtx, return_value_rtx;
+ tree init_type;
+
+ /* Make sure we mark the catch param as used, otherwise we'll get
+ a warning about an unused ((anonymous)). */
+ TREE_USED (decl) = 1;
+
+ /* Figure out the type that the initializer is. */
+ init_type = TREE_TYPE (decl);
+ if (TREE_CODE (init_type) != REFERENCE_TYPE
+ && TREE_CODE (init_type) != POINTER_TYPE)
+ init_type = build_reference_type (init_type);
+
+ exp = get_eh_value ();
+
+ /* Since pointers are passed by value, initialize a reference to
+ pointer catch parm with the address of the value slot. */
+ if (TREE_CODE (init_type) == REFERENCE_TYPE
+ && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
+ exp = build_unary_op (ADDR_EXPR, exp, 1);
+
+ exp = ocp_convert (init_type , exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
+
+ push_eh_cleanup ();
+
+ /* Create a binding level for the parm. */
+ pushlevel (0);
+ expand_start_bindings (0);
+
+ init = convert_from_reference (exp);
+
+ /* If the constructor for the catch parm exits via an exception, we
+ must call terminate. See eh23.C. */
+ if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+ {
+ /* Generate the copy constructor call directly so we can wrap it.
+ See also expand_default_init. */
+ init = ocp_convert (TREE_TYPE (decl), init,
+ CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
+ init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
+ build_terminate_handler ());
+ }
+
+ /* Let `cp_finish_decl' know that this initializer is ok. */
+ DECL_INITIAL (decl) = init;
+ decl = pushdecl (decl);
+
+ cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
+ }
+ else
+ {
+ push_eh_cleanup ();
+
+ /* Create a binding level for the parm. */
+ pushlevel (0);
+ expand_start_bindings (0);
+
+ /* Fall into the catch all section. */
+ }
+
+ init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
+ expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ emit_line_note (input_filename, lineno);
+}
+
/* Call this to end a catch block. Its responsible for emitting the
@@ -658,7 +823,8 @@ expand_end_catch_block ()
/* label we emit to jump to if this catch block didn't match. */
/* This the closing } in the `if (eq) {' of the documentation. */
- emit_label (pop_label_entry (&false_label_stack));
+ if (! flag_new_exceptions)
+ emit_label (pop_label_entry (&false_label_stack));
}
/* An exception spec is implemented more or less like:
@@ -686,7 +852,6 @@ expand_end_eh_spec (raises)
int count = 0;
expand_start_all_catch ();
- start_catch_handler (NULL);
expand_start_catch_block (NULL_TREE, NULL_TREE);
/* Build up an array of type_infos. */
diff --git a/gcc/cp/exception.cc b/gcc/cp/exception.cc
index b081fa7..cad7304 100644
--- a/gcc/cp/exception.cc
+++ b/gcc/cp/exception.cc
@@ -93,6 +93,7 @@ struct cp_eh_info
bool caught;
cp_eh_info *next;
long handlers;
+ void *original_value;
};
/* Language-specific EH info pointer, defined in libgcc2. */
@@ -162,7 +163,10 @@ __cplus_type_matcher (cp_eh_info *info, exception_table *matching_info,
/* 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);
+ ret = __throw_type_match_rtti (match_type, info->type, info->original_value);
+ /* change value of exception */
+ if (ret)
+ info->value = ret;
return ret;
}
@@ -180,11 +184,11 @@ __cp_push_exception (void *value, void *type, void (*cleanup)(void *, int))
p->cleanup = cleanup;
p->handlers = 0;
p->caught = false;
+ p->original_value = value;
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;
cp_eh_info **q = __get_eh_info ();
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index b3b408c..ffc45e6 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -3253,7 +3253,6 @@ function_try_block:
ctor_initializer_opt compstmt
{
expand_start_all_catch ();
- start_catch_handler (NULL);
}
handler_seq
{
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 60c4c32..763f208 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -589,7 +589,6 @@ finish_try_block (try_block)
else
{
expand_start_all_catch ();
- start_catch_handler (NULL);
}
}
diff --git a/gcc/eh-common.h b/gcc/eh-common.h
index c16d66a..c8d98c0 100644
--- a/gcc/eh-common.h
+++ b/gcc/eh-common.h
@@ -92,7 +92,6 @@ typedef void * (*__eh_matcher) PROTO ((void *, void *, void *));
typedef struct __eh_info
{
__eh_matcher match_function;
- void *coerced_value;
short language;
short version;
} __eh_info;
diff --git a/gcc/except.c b/gcc/except.c
index 63d6c82..6ffa920 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -1025,7 +1025,7 @@ get_dynamic_handler_chain ()
/* This is the offset of dynamic_handler_chain in the eh_context struct
declared in eh-common.h. If its location is change, change this offset */
- dhc = plus_constant (ehc, GET_MODE_SIZE (Pmode));
+ dhc = plus_constant (ehc, POINTER_SIZE / BITS_PER_UNIT);
result = copy_to_reg (dhc);
@@ -1045,7 +1045,7 @@ get_dynamic_cleanup_chain ()
rtx dhc, dcc, result;
dhc = get_dynamic_handler_chain ();
- dcc = plus_constant (dhc, GET_MODE_SIZE (Pmode));
+ dcc = plus_constant (dhc, POINTER_SIZE / BITS_PER_UNIT);
result = copy_to_reg (dcc);
@@ -1618,6 +1618,10 @@ expand_start_all_catch ()
expand_eh_region_start ();
ehstack.top->entry->outer_context = outer_context;
}
+
+ /* We also have to start the handler if we aren't using the new model. */
+ if (! flag_new_exceptions)
+ start_catch_handler (NULL);
}
/* Finish up the catch block. At this point all the insns for the
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c
index 1fc703e..4e17faf 100644
--- a/gcc/libgcc2.c
+++ b/gcc/libgcc2.c
@@ -3426,10 +3426,7 @@ find_exception_handler (void *pc, exception_descriptor *table, void *eh_info)
{
ret = (*matcher)(eh_info, &tab[pos], table);
if (ret)
- {
- ((__eh_info *)eh_info)->coerced_value = ret;
- return tab[pos].exception_handler;
- }
+ return tab[pos].exception_handler;
}
}
else