From 5816cb14dd6c7d682888a0cdd52a73e0867edd05 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Tue, 23 Jun 1998 07:10:29 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 9 +++ gcc/cp/ChangeLog | 20 +++++ gcc/cp/except.c | 185 +++++++++++++++++++++++++++++++++++++++++--- gcc/cp/exception.cc | 8 +- gcc/cp/parse.y | 1 - gcc/cp/semantics.c | 1 - gcc/eh-common.h | 1 - gcc/except.c | 8 +- gcc/libgcc2.c | 5 +- 9 files changed, 217 insertions(+), 21 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 69b80ca98b9..d4f3d456c64 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 * varasm.c (assemble_variable): Remove reference to warn_bss_align. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 27a81786e74..ddd56db7337 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 * call.c (joust): Fix confusing conversion warning. diff --git a/gcc/cp/except.c b/gcc/cp/except.c index dba0f0919c4..438351ef8cd 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 b081fa7bcc0..cad73046462 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 b3b408c2a22..ffc45e61c6e 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 60c4c3213c3..763f208cf36 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 c16d66a5008..c8d98c09072 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 63d6c82fc47..6ffa9203867 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 1fc703e84d2..4e17faf4919 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 -- 2.30.2