From a1622f838f1188fca74ba0186300882f33006ae7 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Mon, 8 Jun 1998 12:43:28 +0000 Subject: [PATCH] [multiple changes] Thu Jun 8 14:16:15 EDT 1998 Andrew MacLeod * eh-common.h: Remove NEW_EH_MODEL compile time flag, and replace with flag_new_exceptions runtime flag. (struct old_exception_table): New struct which represents what the exception table looks like without the new model. (NEW_EH_RUNTIME): New value used as a tag in the exception table to flag that this is a new style table. * except.h: Remove compile time flag NEW_EH_MODEL. (expand_builtin_eh_stub_old): New prototype. * tree.h (enum built_in_function): Add BUILT_IN_EH_STUB_OLD. * expr.c (expand_builtin): New builtin func BUILT_IN_EH_STUB_OLD. * c-decl.c (init_decl_processing): Add new builtin function __builtin_eh_stub_old. * final.c (final_scan_insn): Replace compile time flag NEW_EH_MODEL. * flags.h (flag_new_exceptions): New runtime flag. * toplev.c (flag_new_exceptions): Initialize default to 0, -fnew-exceptions sets to 1. * except.c (output_exception_table_entry): Output New style exception identifier into table, and replace compile time flag NEW_EH_MODEL with runtime flag flag_new_exceptions. (output_exception_table): Replace compile time flag NEW_EH_MODEL. (expand_builtin_eh_stub_old): Duplicates original functionality of expand_builtin_eh_stub. (expand_builtin_eh_stub): Replace compile time flag NEW_EH_MODEL. * libgcc2.c (find_exception_handler): Remove NEW_EH_MODEL #ifdefs. (old_find_exception_handler): New func, same as find_exception_handler except it works on the old style exception table. (__throw): Replace NEW_EH_MODEL. Detect new model based on presence of identifier in the exception table, and call appropriate routines. 1998-06-08 Andrew MacLeod * except.c (init_exception_processing): Remove NEW_EH_MODEL compile time flag. Call __cp_eh_info instead of __cp_exception_info. * exception.cc (struct cp_eh_info): Remove NEW_EH_MODEL flag. (__cp_exception_info): Return offset into cp_eh_info structure to match what use to be the start of this structure. (__cp_eh_info): New function to return a pointer to cp_eh_info struct. (__cplus_type_matcher, __cp_push_exception): Remove NEW_EH_MODEL compile time flag. (__uncatch_exception, __check_eh_spec, std::uncaught_exception): Call __cp_eh_info instead of __cp_exception_info. From-SVN: r20336 --- gcc/ChangeLog | 31 ++++++++++++++++ gcc/c-decl.c | 2 + gcc/cp/ChangeLog | 13 +++++++ gcc/cp/except.c | 35 ++++++------------ gcc/cp/exception.cc | 27 ++++++++------ gcc/eh-common.h | 35 +++++------------- gcc/except.c | 90 +++++++++++++++++++++++++-------------------- gcc/except.h | 5 +-- gcc/expr.c | 2 + gcc/final.c | 10 ++--- gcc/flags.h | 5 +++ gcc/libgcc2.c | 88 +++++++++++++++++++++++++++----------------- gcc/toplev.c | 6 +++ gcc/tree.h | 1 + 14 files changed, 208 insertions(+), 142 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 07b0a2bf7d47..b8793820451b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +Mon Jun 8 14:16:15 EDT 1998 Andrew MacLeod + + * eh-common.h: Remove NEW_EH_MODEL compile time flag, and replace with + flag_new_exceptions runtime flag. + (struct old_exception_table): New struct which represents what + the exception table looks like without the new model. + (NEW_EH_RUNTIME): New value used as a tag in the exception table to + flag that this is a new style table. + * except.h: Remove compile time flag NEW_EH_MODEL. + (expand_builtin_eh_stub_old): New prototype. + * tree.h (enum built_in_function): Add BUILT_IN_EH_STUB_OLD. + * expr.c (expand_builtin): New builtin func BUILT_IN_EH_STUB_OLD. + * c-decl.c (init_decl_processing): Add new builtin function + __builtin_eh_stub_old. + * final.c (final_scan_insn): Replace compile time flag NEW_EH_MODEL. + * flags.h (flag_new_exceptions): New runtime flag. + * toplev.c (flag_new_exceptions): Initialize default to 0, + -fnew-exceptions sets to 1. + * except.c (output_exception_table_entry): Output New style exception + identifier into table, and replace compile time flag NEW_EH_MODEL + with runtime flag flag_new_exceptions. + (output_exception_table): Replace compile time flag NEW_EH_MODEL. + (expand_builtin_eh_stub_old): Duplicates original functionality of + expand_builtin_eh_stub. + (expand_builtin_eh_stub): Replace compile time flag NEW_EH_MODEL. + * libgcc2.c (find_exception_handler): Remove NEW_EH_MODEL #ifdefs. + (old_find_exception_handler): New func, same as find_exception_handler + except it works on the old style exception table. + (__throw): Replace NEW_EH_MODEL. Detect new model based on presence + of identifier in the exception table, and call appropriate routines. + Mon Jun 8 01:21:13 1998 Jason Merrill * function.c: Define current_function_cannot_inline. diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 6a0e0eaceeb4..bc8f61773f96 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -3260,6 +3260,8 @@ init_decl_processing () ptr_type_node, endlink)), BUILT_IN_SET_RETURN_ADDR_REG, NULL_PTR); + builtin_function ("__builtin_eh_stub_old", ptr_ftype_void, + BUILT_IN_EH_STUB_OLD, NULL_PTR); builtin_function ("__builtin_eh_stub", ptr_ftype_void, BUILT_IN_EH_STUB, NULL_PTR); builtin_function diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 912b332332ce..f426641638e2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +1998-06-08 Andrew MacLeod + + * except.c (init_exception_processing): Remove NEW_EH_MODEL compile + time flag. Call __cp_eh_info instead of __cp_exception_info. + * exception.cc (struct cp_eh_info): Remove NEW_EH_MODEL flag. + (__cp_exception_info): Return offset into cp_eh_info structure to + match what use to be the start of this structure. + (__cp_eh_info): New function to return a pointer to cp_eh_info struct. + (__cplus_type_matcher, __cp_push_exception): Remove NEW_EH_MODEL + compile time flag. + (__uncatch_exception, __check_eh_spec, std::uncaught_exception): Call + __cp_eh_info instead of __cp_exception_info. + 1998-06-08 Jason Merrill * decl.c (cp_finish_decl): Disable inlining of extern inlines diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 89dee7ee19c9..44e250ca2633 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -203,10 +203,8 @@ 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 @@ -245,25 +243,20 @@ call_eh_info () { tree fn; - fn = get_identifier ("__cp_exception_info"); + fn = get_identifier ("__cp_eh_info"); if (IDENTIFIER_GLOBAL_VALUE (fn)) fn = IDENTIFIER_GLOBAL_VALUE (fn); else { -#ifdef NEW_EH_MODEL - tree t1; -#endif - tree t, fields[7]; - int fo = 0; + tree t1, t, fields[7]; - /* Declare cp_eh_info * __cp_exception_info (void), + /* Declare cp_eh_info * __cp_eh_info (void), as defined in exception.cc. */ push_obstacks_nochange (); end_temporary_allocation (); /* 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); @@ -288,31 +281,27 @@ call_eh_info () /* 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); -#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"), + fields[0] = build_lang_field_decl (FIELD_DECL, + get_identifier ("eh_info"), t1); + fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("value"), ptr_type_node); - fields[1+fo] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"), + fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"), ptr_type_node); - fields[2+fo] = build_lang_field_decl + fields[3] = 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+fo] = build_lang_field_decl (FIELD_DECL, get_identifier ("caught"), + fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("caught"), boolean_type_node); - fields[4+fo] = build_lang_field_decl (FIELD_DECL, get_identifier ("next"), + fields[5] = build_lang_field_decl (FIELD_DECL, get_identifier ("next"), build_pointer_type (t)); - fields[5+fo] = build_lang_field_decl + fields[6] = 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+fo, ptr_type_node); + finish_builtin_type (t, "cp_eh_info", fields, 6, ptr_type_node); t = build_pointer_type (t); /* And now the function. */ diff --git a/gcc/cp/exception.cc b/gcc/cp/exception.cc index 461dba40c34d..b081fa7bcc06 100644 --- a/gcc/cp/exception.cc +++ b/gcc/cp/exception.cc @@ -86,9 +86,7 @@ std::unexpected () struct cp_eh_info { -#ifdef NEW_EH_MODEL __eh_info eh_info; -#endif void *value; void *type; void (*cleanup)(void *, int); @@ -105,11 +103,23 @@ extern "C" cp_eh_info **__get_eh_info (); // actually void ** extern bool __is_pointer (void *); + +/* OLD Compiler hook to return a pointer to the info for the current exception. + Used by get_eh_info (). This fudges the actualy returned value to + point to the beginning of what USE to be the cp_eh_info structure. + THis is so that old code that dereferences this pointer will find + things where it expects it to be.*/ +extern "C" void * +__cp_exception_info (void) +{ + return &((*__get_eh_info ())->value); +} + /* Compiler hook to return a pointer to the info for the current exception. Used by get_eh_info (). */ extern "C" cp_eh_info * -__cp_exception_info (void) +__cp_eh_info (void) { return *__get_eh_info (); } @@ -138,8 +148,6 @@ __eh_free (void *p) } -#ifdef NEW_EH_MODEL - typedef void * (* rtimetype) (void); extern "C" void * @@ -157,7 +165,6 @@ __cplus_type_matcher (cp_eh_info *info, exception_table *matching_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. @@ -174,12 +181,10 @@ __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 (); @@ -227,7 +232,7 @@ __cp_pop_exception (cp_eh_info *p) extern "C" void __uncatch_exception (void) { - cp_eh_info *p = __cp_exception_info (); + cp_eh_info *p = __cp_eh_info (); if (p == 0) terminate (); p->caught = false; @@ -248,7 +253,7 @@ __uncatch_exception (void) extern "C" void __check_eh_spec (int n, const void **spec) { - cp_eh_info *p = __cp_exception_info (); + cp_eh_info *p = __cp_eh_info (); for (int i = 0; i < n; ++i) { @@ -301,7 +306,7 @@ __throw_bad_typeid (void) bool std::uncaught_exception () { - cp_eh_info *p = __cp_exception_info (); + cp_eh_info *p = __cp_eh_info (); return p && ! p->caught; } diff --git a/gcc/eh-common.h b/gcc/eh-common.h index 708946b412a4..51ecf31470e8 100644 --- a/gcc/eh-common.h +++ b/gcc/eh-common.h @@ -5,7 +5,7 @@ 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 +/* The runtime flag flag_new_exceptions 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 @@ -18,17 +18,6 @@ #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 */ @@ -41,23 +30,14 @@ struct eh_context void *info; }; -#endif - - #ifndef EH_TABLE_LOOKUP -#ifndef NEW_EH_MODEL - -typedef struct exception_table +typedef struct old_exception_table { void *start_region; void *end_region; void *exception_handler; -} exception_table; - -typedef exception_table exception_descriptor; - -#else +} old_exception_table; typedef struct exception_table { @@ -76,11 +56,18 @@ typedef struct exception_lang_info short version; } exception_lang_info; +/* This value in the first field of the exception descriptor + identifies the descriptor as the new model format. This value would never + be present in this location under the old model */ + +#define NEW_EH_RUNTIME ((void *) -2) + /* Each function has an exception_descriptor which contains the language info, and a table of exception ranges and handlers */ typedef struct exception_descriptor { + void *runtime_id_field; exception_lang_info lang; exception_table table[1]; } exception_descriptor; @@ -126,8 +113,6 @@ enum exception_source_language EH_LANG_Mips_Assembler = 0x8001 }; -#endif - #endif /* EH_TABLE_LOOKUP */ diff --git a/gcc/except.c b/gcc/except.c index 5881e223d647..b3cb9cdaa2a5 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -1842,23 +1842,20 @@ output_exception_table_entry (file, n) assemble_integer (handler->handler_label, POINTER_SIZE / BITS_PER_UNIT, 1); -#ifdef NEW_EH_MODEL - /* for now make sure the sizes match */ - if (handler->type_info == NULL) - assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1); - else - output_constant ((tree)(handler->type_info), + if (flag_new_exceptions) + { + if (handler->type_info == NULL) + assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1); + else + output_constant ((tree)(handler->type_info), POINTER_SIZE / BITS_PER_UNIT); -#endif - + } putc ('\n', file); /* blank line */ } } /* Output the exception table if we have and need one. */ -#ifdef NEW_EH_MODEL - static short language_code = 0; static short version_code = 0; @@ -1876,7 +1873,6 @@ void set_exception_version_code (code) version_code = code; } -#endif void output_exception_table () @@ -1893,17 +1889,20 @@ output_exception_table () assemble_align (GET_MODE_ALIGNMENT (ptr_mode)); assemble_label ("__EXCEPTION_TABLE__"); -#ifdef NEW_EH_MODEL - assemble_integer (GEN_INT (language_code), 2 , 1); - assemble_integer (GEN_INT (version_code), 2 , 1); - - /* Add enough padding to make sure table aligns on a pointer boundry. */ - i = GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT - 4; - for ( ; i < 0; i = i + GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT) - ; - if (i != 0) - assemble_integer (const0_rtx, i , 1); -#endif + if (flag_new_exceptions) + { + assemble_integer (GEN_INT (NEW_EH_RUNTIME), + POINTER_SIZE / BITS_PER_UNIT, 1); + assemble_integer (GEN_INT (language_code), 2 , 1); + assemble_integer (GEN_INT (version_code), 2 , 1); + + /* Add enough padding to make sure table aligns on a pointer boundry. */ + i = GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT - 4; + for ( ; i < 0; i = i + GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT) + ; + if (i != 0) + assemble_integer (const0_rtx, i , 1); + } for (i = 0; i < eh_table_size; ++i) output_exception_table_entry (asm_out_file, eh_table[i]); @@ -1913,11 +1912,12 @@ output_exception_table () /* Ending marker for table. */ assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1); -#ifndef NEW_EH_MODEL + /* for binary compatability, the old __throw checked the second position for a -1, so we should output at least 2 -1's */ - assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1); -#endif + if (! flag_new_exceptions) + assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1); + putc ('\n', asm_out_file); /* blank line */ } @@ -2423,12 +2423,31 @@ get_reg_for_handler () to the exception handler. __throw will set up the necessary values and then return to the stub. */ +rtx +expand_builtin_eh_stub_old () +{ + rtx stub_start = gen_label_rtx (); + rtx after_stub = gen_label_rtx (); + rtx handler, offset; + + emit_jump (after_stub); + emit_label (stub_start); + + eh_regs (&handler, &offset, 0); + + adjust_stack (offset); + emit_indirect_jump (handler); + emit_label (after_stub); + return gen_rtx_LABEL_REF (Pmode, stub_start); +} + rtx expand_builtin_eh_stub () { rtx stub_start = gen_label_rtx (); rtx after_stub = gen_label_rtx (); rtx handler, offset; + rtx jump_to, temp; emit_jump (after_stub); emit_label (stub_start); @@ -2436,28 +2455,19 @@ expand_builtin_eh_stub () eh_regs (&handler, &offset, 0); adjust_stack (offset); -#ifdef NEW_EH_MODEL /* Handler is in fact a pointer to the _eh_context structure, we need to pick out the handler field (first element), and jump to there, leaving the pointer to _eh_conext in the same hardware register. */ - { - rtx jump_to, temp; - temp = gen_rtx_MEM (Pmode, handler); - MEM_IN_STRUCT_P (temp) = 1; - RTX_UNCHANGING_P (temp) = 1; - emit_insn (gen_rtx_SET (Pmode, offset, temp)); - emit_insn (gen_rtx_USE (Pmode, handler)); + temp = gen_rtx_MEM (Pmode, handler); + MEM_IN_STRUCT_P (temp) = 1; + RTX_UNCHANGING_P (temp) = 1; + emit_insn (gen_rtx_SET (Pmode, offset, temp)); + emit_insn (gen_rtx_USE (Pmode, handler)); - emit_indirect_jump (offset); + emit_indirect_jump (offset); - } - -#else - emit_indirect_jump (handler); - -#endif emit_label (after_stub); return gen_rtx_LABEL_REF (Pmode, stub_start); } diff --git a/gcc/except.h b/gcc/except.h index d2523cb2a81b..9198e41a37e7 100644 --- a/gcc/except.h +++ b/gcc/except.h @@ -149,13 +149,9 @@ 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 @@ -381,6 +377,7 @@ extern void expand_fixup_region_end PROTO((tree)); void expand_builtin_unwind_init PROTO((void)); rtx expand_builtin_dwarf_fp_regnum PROTO((void)); rtx expand_builtin_eh_stub PROTO((void)); +rtx expand_builtin_eh_stub_old PROTO((void)); #ifdef TREE_CODE rtx expand_builtin_frob_return_addr PROTO((tree)); rtx expand_builtin_extract_return_addr PROTO((tree)); diff --git a/gcc/expr.c b/gcc/expr.c index 058d12175dbd..fe276bdbcae5 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -8954,6 +8954,8 @@ expand_builtin (exp, target, subtarget, mode, ignore) case BUILT_IN_SET_RETURN_ADDR_REG: expand_builtin_set_return_addr_reg (TREE_VALUE (arglist)); return const0_rtx; + case BUILT_IN_EH_STUB_OLD: + return expand_builtin_eh_stub_old (); case BUILT_IN_EH_STUB: return expand_builtin_eh_stub (); case BUILT_IN_SET_EH_REGS: diff --git a/gcc/final.c b/gcc/final.c index d30e5b24d813..4679fa31adcb 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -2057,9 +2057,8 @@ 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 + if (! flag_new_exceptions) + add_eh_table_entry (NOTE_BLOCK_NUMBER (insn)); #ifdef ASM_OUTPUT_EH_REGION_BEG ASM_OUTPUT_EH_REGION_BEG (file, NOTE_BLOCK_NUMBER (insn)); #endif @@ -2070,9 +2069,8 @@ 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 + if (flag_new_exceptions) + add_eh_table_entry (NOTE_BLOCK_NUMBER (insn)); #ifdef ASM_OUTPUT_EH_REGION_END ASM_OUTPUT_EH_REGION_END (file, NOTE_BLOCK_NUMBER (insn)); #endif diff --git a/gcc/flags.h b/gcc/flags.h index dccfc54b8bff..2b670054eb6b 100644 --- a/gcc/flags.h +++ b/gcc/flags.h @@ -377,6 +377,11 @@ extern int flag_pic; extern int flag_exceptions; +/* Nonzero means use the new model for exception handling. Replaces + -DNEW_EH_MODEL as a compile option. */ + +extern int flag_new_exceptions; + /* Nonzero means don't place uninitialized global data in common storage by default. */ diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index c8604124a19e..19999311788f 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -3366,12 +3366,42 @@ EH_TABLE_LOOKUP In the advent of a tie, we have to give the last entry, as it represents an inner block. */ +static void * +old_find_exception_handler (void *pc, old_exception_table *table) +{ + if (table) + { + 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].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 (void *) 0; +} + static void * 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 */ @@ -3406,29 +3436,6 @@ find_exception_handler (void *pc, exception_descriptor *table, void *eh_info) 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].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; -#endif } return (void *) 0; @@ -3568,6 +3575,7 @@ __throw () frame_state *sub_udata = &ustruct2; frame_state my_ustruct, *my_udata = &my_ustruct; long args_size; + int new_exception_model; /* This is required for C++ semantics. We must call terminate if we try and rethrow an exception, when there is no exception currently @@ -3611,7 +3619,16 @@ label: if (! udata) break; - handler = find_exception_handler (pc, udata->eh_ptr, eh->info); + if (udata->eh_ptr == NULL) + new_exception_model = 0; + else + new_exception_model = (((exception_descriptor *)(udata->eh_ptr))-> + runtime_id_field == NEW_EH_RUNTIME); + + if (new_exception_model) + handler = find_exception_handler (pc, udata->eh_ptr, eh->info); + else + handler = old_find_exception_handler (pc, udata->eh_ptr); /* If we found one, we can stop searching. */ if (handler) @@ -3630,9 +3647,7 @@ 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. */ @@ -3691,7 +3706,10 @@ label: /* udata now refers to the frame called by the handler frame. */ /* Emit the stub to adjust sp and jump to the handler. */ - retaddr = __builtin_eh_stub (); + if (new_exception_model) + retaddr = __builtin_eh_stub (); + else + retaddr = __builtin_eh_stub_old (); /* And then set our return address to point to the stub. */ if (my_udata->saved[my_udata->retaddr_column] == REG_SAVED_OFFSET) @@ -3702,19 +3720,23 @@ 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, + if (new_exception_model) + __builtin_set_eh_regs ((void *)eh, +#ifdef STACK_GROWS_DOWNWARD + udata->cfa - my_udata->cfa #else - __builtin_set_eh_regs (handler, + my_udata->cfa - udata->cfa #endif + + args_size); + else + __builtin_set_eh_regs (handler, #ifdef STACK_GROWS_DOWNWARD udata->cfa - my_udata->cfa #else my_udata->cfa - udata->cfa #endif - + args_size - ); + + args_size); /* Epilogue: restore the handler frame's register values and return to the stub. */ diff --git a/gcc/toplev.c b/gcc/toplev.c index 60cbc6ac24bc..ed0e1a4a8041 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -600,6 +600,11 @@ int flag_pic; int flag_exceptions; +/* Nonzero means use the new model for exception handling. Replaces + -DNEW_EH_MODEL as a compile option. */ + +extern int flag_new_exceptions = 0; + /* Nonzero means don't place uninitialized global data in common storage by default. */ @@ -759,6 +764,7 @@ struct { char *string; int *variable; int on_value;} f_options[] = {"pic", &flag_pic, 1}, {"PIC", &flag_pic, 2}, {"exceptions", &flag_exceptions, 1}, + {"new-exceptions", &flag_new_exceptions, 1}, {"sjlj-exceptions", &exceptions_via_longjmp, 1}, {"asynchronous-exceptions", &asynchronous_exceptions, 1}, {"profile-arcs", &profile_arc_flag, 1}, diff --git a/gcc/tree.h b/gcc/tree.h index b864020af1f1..c7779dd7bfd5 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -116,6 +116,7 @@ enum built_in_function BUILT_IN_FROB_RETURN_ADDR, BUILT_IN_EXTRACT_RETURN_ADDR, BUILT_IN_SET_RETURN_ADDR_REG, + BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS, -- 2.43.5