diff options
author | Andrew MacLeod <amacleod@cygnus.com> | 1998-06-23 07:10:29 +0000 |
---|---|---|
committer | Andrew Macleod <amacleod@gcc.gnu.org> | 1998-06-23 07:10:29 +0000 |
commit | 5816cb14dd6c7d682888a0cdd52a73e0867edd05 (patch) | |
tree | caff48e4d357cdb27c61741d2e59101bb1bba09b /gcc | |
parent | 83de03dfd8d9c845da0d3370839dbf1518c48f52 (diff) | |
download | gcc-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/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/cp/except.c | 185 | ||||
-rw-r--r-- | gcc/cp/exception.cc | 8 | ||||
-rw-r--r-- | gcc/cp/parse.y | 1 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 1 | ||||
-rw-r--r-- | gcc/eh-common.h | 1 | ||||
-rw-r--r-- | gcc/except.c | 8 | ||||
-rw-r--r-- | gcc/libgcc2.c | 5 |
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 |