+Mon Jun 8 14:16:15 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
* function.c: Define current_function_cannot_inline.
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
+1998-06-08 Andrew MacLeod <amacleod@cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
* decl.c (cp_finish_decl): Disable inlining of extern inlines
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
{
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);
/* 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. */
struct cp_eh_info
{
-#ifdef NEW_EH_MODEL
__eh_info eh_info;
-#endif
void *value;
void *type;
void (*cleanup)(void *, int);
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 ();
}
}
-#ifdef NEW_EH_MODEL
-
typedef void * (* rtimetype) (void);
extern "C" void *
ret = __throw_type_match_rtti (match_type, info->type, info->value);
return ret;
}
-#endif
/* Compiler hook to push a new exception onto the stack.
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 ();
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;
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)
{
bool
std::uncaught_exception ()
{
- cp_eh_info *p = __cp_exception_info ();
+ cp_eh_info *p = __cp_eh_info ();
return p && ! p->caught;
}
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
#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 */
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
{
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;
EH_LANG_Mips_Assembler = 0x8001
};
-#endif
-
#endif /* EH_TABLE_LOOKUP */
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;
version_code = code;
}
-#endif
void
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]);
/* 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 */
}
\f
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);
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);
}
/* 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
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));
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:
&& ! 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
&& ! 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
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. */
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 */
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;
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
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)
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 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)
/* 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. */
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. */
{"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},
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,