IA-64 ABI Exception Handling.

From-SVN: r40924
This commit is contained in:
Richard Henderson 2001-03-28 03:04:51 -08:00 committed by Richard Henderson
parent ce1c98ea45
commit 52a11cbfcf
100 changed files with 10324 additions and 9742 deletions

View File

@ -1,3 +1,117 @@
2001-03-28 Richard Henderson <rth@redhat.com>
* except.c: Rewrite entirely for IA-64 ABI exception handling.
* except.h: Likewise.
* Makefile.in (LIB2ADDEH): Mention unwind-dw2*.c
(LIB2ADDEHDEP): New.
(LIB2FUNCS_EH): Remove.
(LIB2ADD): Remove LIB2ADDEH.
(libgcc.mk): Pass LIB2ADDEHDEP, don't pass LIB2FUNCS_EH.
(LIBGCC_DEPS): Use LIB2ADDEHDEP.
(crt{begin,end}[S].o): Likewise.
(except.o): Update includes.
* mklibgcc.in: Remove LIB2FUNCS_EH, add LIB2ADDEH, LIB2ADDEHDEP.
(libgcc2_c_dep): Use LIB2ADDEHDEP.
* basic-block.h (struct basic_block_def): Remove eh_beg, eh_end.
* bb-reorder.c (reorder_basic_blocks): Don't disable for EH.
* builtins.def (BUILT_IN_EH_RETURN_DATA_REGNO): New.
* builtins.c (expand_builtin): Implement it.
[BUILT_IN_EH_RETURN]: Update for nr arguments change.
* c-common.c (c_common_nodes_and_builtins): Declare it.
* c-decl.c (init_decl_processing): Update __builtin_eh_return.
* calls.c (libfunc_nothrow): Remove.
(emit_library_call_value_1): Don't call it.
* crtstuff.c: Include unwind-dw2-fde.h instead of frame.h.
* dwarf2.h (dwarf_call_frame_info): Add dwarf2.1 elements.
(DW_EH_PE_*): New defines for pointer encoding in .eh_frame.
* dwarf2out.c (struct dw_fde_struct): Add uses_eh_lsda, funcdef_number.
(current_funcdef_number): Globalize.
(output_call_frame_info): Emit frame data if an lsda is needed.
Generate augmentation for personality routine. Don't play with
difference symbols.
(dwarf2out_begin_prologue): Record funcdef_number.
* dwarf2out.h (current_funcdef_number): Declare.
* expr.c (expand_expr): Update for except.h name changes.
Remove POPDCC_EXPR, POPDHC_EXPR. Add EXC_PTR_EXPR.
* expr.h (LTI_throw, LTI_rethrow): Remove.
(LTI_sjthrow, LTI_sjpopnthrow, LTI_terminate): Remove.
(LTI_eh_rtime_match): Remove.
(LTI_unwind_resume, LTI_eh_personality): Add.
(LTI_unwind_sjlj_register, LTI_unwind_sjlj_unregister): Add.
* final.c (final): Don't call check_exception_handler_labels,
init_insn_eh_region, or free_insn_eh_region.
(final_scan_insn): Always emit debug labels for
NOTE_INSN_EH_REGION notes.
* flags.h (flag_new_exceptions): Remove.
* flow.c (entry_exit_blocks): Remove eh_beg, eh_end.
(record_active_eh_regions): Remove.
(count_basic_blocks): Check all instructions for REG_EH_REGION.
Use can_throw_internal.
(find_basic_blocks_1): Likewise.
(move_stray_eh_region_notes): Remove.
(find_label_refs): No eh_return_stub_label.
(make_edges): Likewise. No init/free_eh_nesting_info. Handle RESX.
(make_eh_edge): No eh_nest_info. Update for reachable_handlers
changes.
(delete_unreachable_blocks): Don't track deleted handlers.
(flow_delete_block): Use maybe_remove_eh_handler.
(delete_eh_regions): Remove.
(merge_blocks): Don't check for eh region match.
(mark_regs_live_at_end): Handle EH_RETURN_DATA_REGNO,
EH_RETURN_STACKADJ_RTX, EH_RETURN_HANDLER_RTX.
(init_propagate_block_info): Disable dead frame store optimization
when current_function_calls_eh_return.
(dump_bb): Don't print eh_beg, eh_end.
* function.c (fixup_var_refs): No catch_clauses.
(expand_function_end): Likewise. Call expand_eh_return before
the return register use. Call sjlj_emit_function_exit_after.
(expand_function_start): Force pseudo DECL_RESULT if sjlj exceptions.
* function.h (struct function): Add calls_eh_return, uses_eh_lsda.
* ifcvt.c (dead_or_predicable): Remove eh region check.
* integrate.c (function_cannot_inline_p): Disallow __builtin_eh_return.
Don't check for EH vs parameters.
(expand_inline_function_eh_labelmap, eif_eh_map): Remove.
(expand_inline_function): Call duplicate_eh_regions.
(copy_insn_list): Don't handle NOTE_INSN_EH_REGION_BEG/END.
(copy_insn_notes): Remap REG_EH_REGION notes.
(copy_rtx_and_substitute): Remove SYMBOL_REF_NEED_ADJUST check.
* integrate.h (struct inline_remap): Add local_return_label.
* jump.c (jump_optimize_1): Don't init/free_insn_eh_region, nor
check_exception_handler_labels, nor exception_optimize.
(find_cross_jump): No EH region check.
* optabs.c (init_optabs): Update for changed eh libfuncs.
* rtl.def (RESX): New.
* rtl.h (SYMBOL_REF_NEED_ADJUST): Remove.
* stmt.c (expand_decl_cleanup): Simplify using_eh_for_cleanups_p
checks. Update for except.h name changes.
(expand_cleanups): Likewise.
(expand_dcc_cleanup, expand_dhc_cleanup): Remove.
* toplev.c (dump_file_index, dump_file): Add .02.eh dump.
(compile_file): Call init_eh before init_optabs. Don't
output_exception_table here.
(rest_of_compilation): Call convert_from_eh_region_ranges,
convert_to_eh_region_ranges, output_function_exception_table.
Don't emit_eh_context.
* tree.def (POPDHC_EXPR, POPDCC_EXPR): Remove.
(EXC_PTR_EXPR): New.
* md.texi (eh_epilogue): Remove.
(eh_return): Document.
* tm.texi (EH_RETURN_DATA_REGNO): Document.
(EH_RETURN_STACKADJ_RTX, EH_RETURN_HANDLER_RTX): Document.
* eh-common.h: Remove file.
* frame-dwarf2.c, frame.c, frame.h: Remove files.
* libgcc2.c (L_eh): Remove.
* unwind-dw2-fde.c: New file, largely copied from frame.c.
* unwind-dw2-fde.h: New file.
* unwind-dw2.c: New file, largely cribbed from frame-dwarf2.c.
* unwind-sjlj.c, unwind.h, unwind.inc: New files.
* libgcc-std.ver: Update for eh symbols.
2001-03-27 Richard Henderson <rth@redhat.com>
* regmove.c (perhaps_ends_bb_p): Use can_throw_internal to

View File

@ -397,8 +397,10 @@ LIBGCC2_INCLUDES =
# Additional target-dependent options for compiling libgcc2.a.
TARGET_LIBGCC2_CFLAGS =
# Additional sources to handle exceptions; overridden by some targets.
LIB2ADDEH = $(srcdir)/frame-dwarf2.c
# Additional sources to handle exceptions; overridden on ia64.
LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
$(srcdir)/unwind-sjlj.c
LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
# libgcc1-test target (must also be overridable for a target)
LIBGCC1_TEST = libgcc1-test
@ -794,8 +796,6 @@ LIB2FUNCS = _muldi3 _divdi3 _moddi3 _udivdi3 _umoddi3 _negdi2 \
_mulvsi3 _mulvdi3 _negvsi2 _negvdi2 \
_ctors
LIB2FUNCS_EH = _eh
FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
_fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \
_lt_sf _le_sf _unord_sf _si_to_sf _sf_to_si _negate_sf _make_sf \
@ -1033,7 +1033,7 @@ xlimits.h: glimits.h limitx.h limity.h
#
# Build libgcc.a.
LIB2ADD = $(LIB2ADDEH) $(LIB2FUNCS_EXTRA)
LIB2ADD = $(LIB2FUNCS_EXTRA)
libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) xgcc$(exeext)
objext='$(objext)' \
@ -1043,8 +1043,9 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) xgcc$(exeext)
LIB1ASMFUNCS='$(LIB1ASMFUNCS)' \
LIB1FUNCS_EXTRA='$(LIB1FUNCS_EXTRA)' \
LIB2FUNCS='$(LIB2FUNCS)' \
LIB2FUNCS_EH='$(LIB2FUNCS_EH)' \
LIB2ADD='$(LIB2ADD)' \
LIB2ADDEH='$(LIB2ADDEH)' \
LIB2ADDEHDEP='$(LIB2ADDEHDEP)' \
FPBIT='$(FPBIT)' \
FPBIT_FUNCS='$(FPBIT_FUNCS)' \
DPBIT='$(DPBIT)' \
@ -1064,8 +1065,9 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) xgcc$(exeext)
# All the things that might cause us to want to recompile bits of libgcc.
LIBGCC_DEPS = $(GCC_PASSES) $(LANGUAGES) stmp-int-hdrs $(STMP_FIXPROTO) \
libgcc.mk $(srcdir)/libgcc1.c $(srcdir)/libgcc2.c $(TCONFIG_H) \
$(MACHMODE_H) longlong.h frame.h gbl-ctors.h config.status \
stmp-int-hdrs tsystem.h $(FPBIT) $(DPBIT) $(LIB2ADD) $(EXTRA_PARTS)
$(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs \
tsystem.h $(FPBIT) $(DPBIT) $(LIB2ADD) $(LIB2ADDEH) $(LIB2ADDEHDEP) \
$(EXTRA_PARTS)
libgcc.a: $(LIBGCC_DEPS)
$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
@ -1125,14 +1127,14 @@ stmp-multilib: $(LIBGCC_DEPS)
# linked using GCC on systems using COFF or ELF, for the sake of C++
# constructors.
$(T)crtbegin.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
frame.h gbl-ctors.h stmp-int-hdrs tsystem.h
gbl-ctors.h stmp-int-hdrs tsystem.h
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
-finhibit-size-directive -fno-inline-functions \
-fno-exceptions $(CRTSTUFF_T_CFLAGS) @inhibit_libc@ \
-c $(srcdir)/crtstuff.c -DCRT_BEGIN -o $(T)crtbegin$(objext)
$(T)crtend.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
frame.h gbl-ctors.h stmp-int-hdrs tsystem.h
gbl-ctors.h stmp-int-hdrs tsystem.h
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
-finhibit-size-directive -fno-inline-functions \
-fno-exceptions $(CRTSTUFF_T_CFLAGS) @inhibit_libc@ \
@ -1140,7 +1142,7 @@ $(T)crtend.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
# These are versions of crtbegin and crtend for shared libraries.
$(T)crtbeginS.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
frame.h gbl-ctors.h stmp-int-hdrs tsystem.h
gbl-ctors.h stmp-int-hdrs tsystem.h
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
-finhibit-size-directive -fno-inline-functions \
-fno-exceptions $(CRTSTUFF_T_CFLAGS_S) @inhibit_libc@ \
@ -1148,7 +1150,7 @@ $(T)crtbeginS.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
-o $(T)crtbeginS$(objext)
$(T)crtendS.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
frame.h gbl-ctors.h stmp-int-hdrs tsystem.h
gbl-ctors.h stmp-int-hdrs tsystem.h
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
-finhibit-size-directive -fno-inline-functions \
-fno-exceptions $(CRTSTUFF_T_CFLAGS_S) @inhibit_libc@ \
@ -1394,8 +1396,9 @@ stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h function.h \
insn-config.h hard-reg-set.h $(EXPR_H) except.h \
$(LOOP_H) $(RECOG_H) toplev.h output.h varray.h $(GGC_H) $(TM_P_H)
except.o : except.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
function.h $(EXPR_H) $(REGS_H) hard-reg-set.h \
insn-config.h $(RECOG_H) output.h except.h toplev.h intl.h $(GGC_H) $(TM_P_H)
except.h function.h $(EXPR_H) integrate.h \
insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
dwarf2asm.h dwarf2out.h toplev.h $(HASHTAB_H) intl.h $(GGC_H)
expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h function.h \
$(REGS_H) $(EXPR_H) insn-config.h $(RECOG_H) \
output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h except.h \
@ -1414,7 +1417,7 @@ explow.o : explow.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
toplev.h function.h $(TM_P_H)
optabs.o : optabs.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
insn-config.h $(EXPR_H) $(RECOG_H) reload.h \
toplev.h $(GGC_H) real.h $(TM_P_H)
toplev.h $(GGC_H) real.h $(TM_P_H) except.h
dbxout.o : dbxout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h $(REGS_H) \
insn-config.h reload.h gstab.h xcoffout.h output.h dbxout.h toplev.h \
$(TM_P_H)

View File

@ -174,14 +174,12 @@ typedef struct basic_block_def {
/* The index of this block. */
int index;
/* The loop depth of this block plus one. */
/* The loop depth of this block. */
int loop_depth;
/* The active eh region before head and after end. */
int eh_beg, eh_end;
int count; /* Expected number of executions: calculated in
profile.c */
/* Expected number of executions: calculated in profile.c. */
int count;
} *basic_block;
/* Number of basic blocks in the current function. */

View File

@ -92,7 +92,6 @@
#include "flags.h"
#include "output.h"
#include "function.h"
#include "except.h"
#include "toplev.h"
#include "recog.h"
#include "expr.h"
@ -395,8 +394,6 @@ make_reorder_chain_1 (bb, prev)
taken = probability > REG_BR_PROB_BASE / 2;
/* Find the normal taken edge and the normal fallthru edge.
Note that there may in fact be other edges due to
flag_non_call_exceptions.
Note, conditional jumps with other side effects may not
be fully optimized. In this case it is possible for
@ -1356,17 +1353,6 @@ reorder_basic_blocks ()
if (n_basic_blocks <= 1)
return;
/* We do not currently handle correct re-placement of EH notes.
But that does not matter unless we intend to use them. */
if (flag_exceptions)
for (i = 0; i < n_basic_blocks; i++)
{
edge e;
for (e = BASIC_BLOCK (i)->succ; e ; e = e->succ_next)
if (e->flags & EDGE_EH)
return;
}
for (i = 0; i < n_basic_blocks; i++)
BASIC_BLOCK (i)->aux = xcalloc (1, sizeof (struct reorder_block_def));

View File

@ -3605,9 +3605,12 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
case BUILT_IN_EH_RETURN:
expand_builtin_eh_return (TREE_VALUE (arglist),
TREE_VALUE (TREE_CHAIN (arglist)),
TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))));
TREE_VALUE (TREE_CHAIN (arglist)));
return const0_rtx;
#ifdef EH_RETURN_DATA_REGNO
case BUILT_IN_EH_RETURN_DATA_REGNO:
return expand_builtin_eh_return_data_regno (arglist);
#endif
case BUILT_IN_VARARGS_START:
return expand_builtin_va_start (0, arglist);
case BUILT_IN_STDARG_START:

View File

@ -97,6 +97,7 @@ DEF_BUILTIN(BUILT_IN_INIT_DWARF_REG_SIZES)
DEF_BUILTIN(BUILT_IN_FROB_RETURN_ADDR)
DEF_BUILTIN(BUILT_IN_EXTRACT_RETURN_ADDR)
DEF_BUILTIN(BUILT_IN_EH_RETURN)
DEF_BUILTIN(BUILT_IN_EH_RETURN_DATA_REGNO)
DEF_BUILTIN(BUILT_IN_VARARGS_START)
DEF_BUILTIN(BUILT_IN_STDARG_START)

View File

@ -3146,6 +3146,11 @@ c_common_nodes_and_builtins ()
builtin_function ("__builtin_frame_address", ptr_ftype_unsigned,
BUILT_IN_FRAME_ADDRESS, BUILT_IN_NORMAL, NULL_PTR);
#ifdef EH_RETURN_DATA_REGNO
builtin_function ("__builtin_eh_return_data_regno", int_ftype_int,
BUILT_IN_EH_RETURN_DATA_REGNO, BUILT_IN_NORMAL, NULL_PTR);
#endif
builtin_function ("__builtin_alloca", ptr_ftype_sizetype,
BUILT_IN_ALLOCA, BUILT_IN_NORMAL, "alloca");
builtin_function_2 ("__builtin_ffs", "ffs",

View File

@ -3084,12 +3084,11 @@ init_decl_processing ()
builtin_function
("__builtin_eh_return",
build_function_type (void_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE,
type_for_mode (ptr_mode, 0),
tree_cons (NULL_TREE,
type_for_mode (ptr_mode, 0),
tree_cons (NULL_TREE,
ptr_type_node,
endlink)))),
ptr_type_node,
endlink))),
BUILT_IN_EH_RETURN, BUILT_IN_NORMAL, NULL_PTR);
pedantic_lvalues = pedantic;

View File

@ -204,7 +204,6 @@ static void compute_argument_addresses PARAMS ((struct arg_data *,
static rtx rtx_for_function_call PARAMS ((tree, tree));
static void load_register_parameters PARAMS ((struct arg_data *,
int, rtx *, int));
static int libfunc_nothrow PARAMS ((rtx));
static rtx emit_library_call_value_1 PARAMS ((int, rtx, rtx,
enum libcall_type,
enum machine_mode,
@ -3444,22 +3443,6 @@ expand_call (exp, target, ignore)
return target;
}
/* Returns nonzero if FUN is the symbol for a library function which can
not throw. */
static int
libfunc_nothrow (fun)
rtx fun;
{
if (fun == throw_libfunc
|| fun == rethrow_libfunc
|| fun == sjthrow_libfunc
|| fun == sjpopnthrow_libfunc)
return 0;
return 1;
}
/* Output a library call to function FUN (a SYMBOL_REF rtx).
The RETVAL parameter specifies whether return value needs to be saved, other
parameters are documented in the emit_library_call function bellow. */
@ -3501,7 +3484,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
rtx valreg;
int pcc_struct_value = 0;
int struct_value_size = 0;
int flags = 0;
int flags;
int reg_parm_stack_space = 0;
int needed;
rtx before_call;
@ -3525,6 +3508,9 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
#endif
#endif
/* No library functions can throw. */
flags = ECF_NOTHROW;
if (fn_type == LCT_CONST_MAKE_BLOCK)
flags |= ECF_CONST;
else if (fn_type == LCT_PURE_MAKE_BLOCK)
@ -3533,9 +3519,6 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
flags |= ECF_NORETURN;
fun = orgfun;
if (libfunc_nothrow (fun))
flags |= ECF_NOTHROW;
#ifdef PREFERRED_STACK_BOUNDARY
/* Ensure current function's preferred stack boundary is at least
what we need. */

View File

@ -1,3 +1,59 @@
2001-03-28 Richard Henderson <rth@redhat.com>
IA-64 ABI Exception Handling:
* cp-tree.def (EH_SPEC_BLOCK): New.
(MUST_NOT_THROW_EXPR): New.
* cp-tree.h: Update changed function declarations.
(CPTI_PUSH_EXCEPTION_IDENTIFIER): Remove.
(CPTI_CALL_UNEXPECTED): New.
(struct cp_language_function): Rename x_eh_spec_try_block
to x_eh_spec_block.
(EH_SPEC_STMTS, EH_SPEC_RAISES): New.
* decl.c (current_binding_level): If no current function
bindings, revert to scope_chain.
(initialize_predefined_identifiers): Remove __cp_push_exception.
(store_parm_decls): Use begin_eh_spec_block.
(finish_function): Use finish_eh_spec_block.
(mark_lang_function): Update for name changes.
* decl2.c (finish_file): No mark_all_runtime_matches.
* dump.c (cp_dump_tree): Handle new tree codes.
* error.c (dump_expr) [BIND_EXPR]: Fix typo.
* except.c (catch_language_init, catch_language): Remove.
(init_exception_processing): Don't set language code.
Initialize call_unexpected_node, protect_cleanup_actions,
eh_personality_libfunc, lang_eh_runtime_type.
(call_eh_info, push_eh_info, get_eh_info, get_eh_value): Remove.
(get_eh_type, get_eh_caught, get_eh_handlers): Remove.
(prepare_eh_type): Split out type canonicalizations ...
(build_eh_type_type): ... from here.
(build_eh_type_type_ref): Remove.
(mark_all_runtime_matches): Remove.
(build_exc_ptr): New.
(do_begin_catch, do_end_catch): New.
(do_pop_exception): Remove.
(build_terminate_handler): Remove.
(choose_personality_routine): Split out language choice from ...
(initialize_handler_parm): ... here.
Use MUST_NOT_THROW_EXPR.
(expand_start_catch_block): Use do_begin_catch. Simplify Java
exception object handling.
(expand_start_eh_spec, expand_end_eh_spec): Remove.
(expand_exception_blocks, alloc_eh_object): Remove.
(begin_eh_spec_block, finish_eh_spec_block): New.
(do_allocate_exception, do_free_exception): New.
(expand_throw): Merge into ...
(build_throw): ... here. Update for abi.
* expr.c (cplus_expand_expr): No expand_internal_throw.
Handle MUST_NOT_THROW_EXPR.
* pt.c (tsubst_expr): Handle EH_SPEC_BLOCK.
* semantics.c (*) Update for except.h name changes.
(genrtl_try_block): No protect_with_terminate.
(genrtl_eh_spec_block): New.
(genrtl_handler): Don't emit the goto here.
(cp_expand_stmt): Handle EH_SPEC_BLOCK.
(genrtl_finish_function): Don't expand_exception_blocks.
* tree.c (cp_statement_code_p): Handle EH_SPEC_BLOCK.
2001-03-28 Richard Henderson <rth@redhat.com>
* decl.c (struct named_label_list): Rename eh_region to

View File

@ -236,8 +236,13 @@ DEFTREECODE (START_CATCH_STMT, "start_catch_stmt", 'e', 0)
DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
DEFTREECODE (TRY_BLOCK, "try_block", 'e', 2)
DEFTREECODE (EH_SPEC_BLOCK, "eh_spec_block", 'e', 2)
DEFTREECODE (HANDLER, "handler", 'e', 2)
/* A MUST_NOT_THROW_EXPR wraps an expression that may not
throw, and must call terminate if it does. */
DEFTREECODE (MUST_NOT_THROW_EXPR, "must_not_throw_expr", 'e', 1)
DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
/* And some codes for expressing conversions for overload resolution. */

View File

@ -616,7 +616,6 @@ enum cp_tree_index
CPTI_PFN_IDENTIFIER,
CPTI_PFN_OR_DELTA2_IDENTIFIER,
CPTI_VPTR_IDENTIFIER,
CPTI_PUSH_EXCEPTION_IDENTIFIER,
CPTI_STD_IDENTIFIER,
CPTI_LANG_NAME_C,
@ -627,6 +626,7 @@ enum cp_tree_index
CPTI_NULL,
CPTI_JCLASS,
CPTI_TERMINATE,
CPTI_CALL_UNEXPECTED,
CPTI_ATEXIT,
CPTI_DSO_HANDLE,
CPTI_DCAST,
@ -740,9 +740,6 @@ extern tree cp_global_trees[CPTI_MAX];
#define pfn_identifier cp_global_trees[CPTI_PFN_IDENTIFIER]
#define pfn_or_delta2_identifier cp_global_trees[CPTI_PFN_OR_DELTA2_IDENTIFIER]
#define vptr_identifier cp_global_trees[CPTI_VPTR_IDENTIFIER]
/* The name of the function to call to push an exception onto the
exception stack. */
#define cp_push_exception_identifier cp_global_trees[CPTI_PUSH_EXCEPTION_IDENTIFIER]
/* The name of the std namespace. */
#define std_identifier cp_global_trees[CPTI_STD_IDENTIFIER]
#define lang_name_c cp_global_trees[CPTI_LANG_NAME_C]
@ -761,6 +758,9 @@ extern tree cp_global_trees[CPTI_MAX];
/* The declaration for `std::terminate'. */
#define terminate_node cp_global_trees[CPTI_TERMINATE]
/* The declaration for "__cxa_call_unexpected". */
#define call_unexpected_node cp_global_trees[CPTI_CALL_UNEXPECTED]
/* A pointer to `std::atexit'. */
#define atexit_node cp_global_trees[CPTI_ATEXIT]
@ -872,7 +872,7 @@ struct cp_language_function
tree x_dtor_label;
tree x_current_class_ptr;
tree x_current_class_ref;
tree x_eh_spec_try_block;
tree x_eh_spec_block;
tree x_in_charge_parm;
tree x_vtt_parm;
@ -916,10 +916,10 @@ struct cp_language_function
#define current_class_ref \
(cfun ? cp_function_chain->x_current_class_ref : NULL_TREE)
/* The TRY_BLOCK for the exception-specifiers for the current
/* The EH_SPEC_BLOCK for the exception-specifiers for the current
function, if any. */
#define current_eh_spec_try_block cp_function_chain->x_eh_spec_try_block
#define current_eh_spec_block cp_function_chain->x_eh_spec_block
/* The `__in_chrg' parameter for the current function. Only used for
constructors and destructors. */
@ -3035,6 +3035,9 @@ extern int flag_new_for_scope;
#define TRY_STMTS(NODE) TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0)
#define TRY_HANDLERS(NODE) TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 1)
#define EH_SPEC_STMTS(NODE) TREE_OPERAND (EH_SPEC_BLOCK_CHECK (NODE), 0)
#define EH_SPEC_RAISES(NODE) TREE_OPERAND (EH_SPEC_BLOCK_CHECK (NODE), 1)
/* Nonzero if this try block is a function try block. */
#define FN_TRY_BLOCK_P(NODE) TREE_LANG_FLAG_3 (TRY_BLOCK_CHECK (NODE))
#define HANDLER_PARMS(NODE) TREE_OPERAND (HANDLER_CHECK (NODE), 0)
@ -4000,9 +4003,9 @@ extern void init_exception_processing PARAMS ((void));
extern tree expand_start_catch_block PARAMS ((tree));
extern void expand_end_catch_block PARAMS ((tree));
extern void expand_builtin_throw PARAMS ((void));
extern tree expand_start_eh_spec PARAMS ((void));
extern void expand_end_eh_spec PARAMS ((tree, tree));
extern void expand_eh_spec_block PARAMS ((tree));
extern void expand_exception_blocks PARAMS ((void));
extern tree build_exc_ptr PARAMS ((void));
extern tree build_throw PARAMS ((tree));
extern void mark_all_runtime_matches PARAMS ((void));
extern int nothrow_libfn_p PARAMS ((tree));
@ -4256,6 +4259,8 @@ extern tree finish_case_label PARAMS ((tree, tree));
extern tree finish_goto_stmt PARAMS ((tree));
extern tree begin_try_block PARAMS ((void));
extern void finish_try_block PARAMS ((tree));
extern tree begin_eh_spec_block PARAMS ((void));
extern void finish_eh_spec_block PARAMS ((tree, tree));
extern void finish_handler_sequence PARAMS ((tree));
extern tree begin_function_try_block PARAMS ((void));
extern void finish_function_try_block PARAMS ((tree));

View File

@ -478,7 +478,7 @@ struct binding_level
/* The binding level currently in effect. */
#define current_binding_level \
(cfun \
(cfun && cp_function_chain->bindings \
? cp_function_chain->bindings \
: scope_chain->bindings)
@ -6306,7 +6306,6 @@ initialize_predefined_identifiers ()
{ VTABLE_PFN_NAME, &pfn_identifier, 0 },
{ "__pfn_or_delta2", &pfn_or_delta2_identifier, 0 },
{ "_vptr", &vptr_identifier, 0 },
{ "__cp_push_exception", &cp_push_exception_identifier, 0 },
{ "__vtt_parm", &vtt_parm_identifier, 0 },
{ "std", &std_identifier, 0 },
{ NULL, NULL, 0 }
@ -13721,7 +13720,7 @@ store_parm_decls (current_function_parms)
if (flag_exceptions && !processing_template_decl
&& flag_enforce_eh_specs
&& TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
current_eh_spec_try_block = expand_start_eh_spec ();
current_eh_spec_block = begin_eh_spec_block ();
}
@ -13966,9 +13965,9 @@ finish_function (flags)
if (flag_exceptions && !processing_template_decl
&& flag_enforce_eh_specs
&& TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS
(TREE_TYPE (current_function_decl)),
current_eh_spec_try_block);
finish_eh_spec_block (TYPE_RAISES_EXCEPTIONS
(TREE_TYPE (current_function_decl)),
current_eh_spec_block);
}
/* If we're saving up tree structure, tie off the function now. */
@ -14395,7 +14394,7 @@ mark_lang_function (p)
ggc_mark_tree (p->x_dtor_label);
ggc_mark_tree (p->x_current_class_ptr);
ggc_mark_tree (p->x_current_class_ref);
ggc_mark_tree (p->x_eh_spec_try_block);
ggc_mark_tree (p->x_eh_spec_block);
ggc_mark_tree_varray (p->x_local_names);
mark_named_label_lists (&p->x_named_labels, &p->x_named_label_uses);

View File

@ -3621,10 +3621,6 @@ finish_file ()
}
}
/* Mark all functions that might deal with exception-handling as
referenced. */
mark_all_runtime_matches ();
/* We lie to the back-end, pretending that some functions are
not defined when they really are. This keeps these functions
from being put out unnecessarily. But, we must stop lying

View File

@ -188,6 +188,13 @@ cp_dump_tree (di, t)
dump_next_stmt (di, t);
break;
case EH_SPEC_BLOCK:
dump_stmt (di, t);
dump_child ("body", EH_SPEC_STMTS (t));
dump_child ("raises", EH_SPEC_RAISES (t));
dump_next_stmt (di, t);
break;
case PTRMEM_CST:
dump_child ("clas", PTRMEM_CST_CLASS (t));
dump_child ("mbr", PTRMEM_CST_MEMBER (t));
@ -227,6 +234,12 @@ cp_dump_tree (di, t)
dump_next_stmt (di, t);
break;
case MUST_NOT_THROW_EXPR:
dump_stmt (di, t);
dump_child ("body", TREE_OPERAND (t, 0));
dump_next_stmt (di, t);
break;
case SUBOBJECT:
dump_stmt (di, t);
dump_child ("clnp", TREE_OPERAND (t, 0));

View File

@ -2104,7 +2104,7 @@ dump_expr (t, flags)
break;
case BIND_EXPR:
output_add_character (scratch_buffer, '}');
output_add_character (scratch_buffer, '{');
dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS);
output_add_character (scratch_buffer, '}');
break;

File diff suppressed because it is too large Load Diff

View File

@ -88,6 +88,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
tree type = TREE_TYPE (exp);
register enum machine_mode mode = TYPE_MODE (type);
register enum tree_code code = TREE_CODE (exp);
rtx ret;
/* No sense saving up arithmetic to be done
if it's all in the wrong mode to form part of an address.
@ -103,16 +104,19 @@ cplus_expand_expr (exp, target, tmode, modifier)
target, tmode, modifier);
case OFFSET_REF:
{
return expand_expr (default_conversion (resolve_offset_ref (exp)),
target, tmode, EXPAND_NORMAL);
}
return expand_expr (default_conversion (resolve_offset_ref (exp)),
target, tmode, EXPAND_NORMAL);
case THROW_EXPR:
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
expand_internal_throw ();
return NULL;
case MUST_NOT_THROW_EXPR:
expand_eh_region_start ();
ret = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
expand_eh_region_end_must_not_throw (build_call (terminate_node, 0));
return ret;
case EMPTY_CLASS_EXPR:
/* We don't need to generate any code for an empty class. */
return const0_rtx;

View File

@ -51,6 +51,7 @@ static tree simplify_aggr_init_exprs_r PARAMS ((tree *, int *, void *));
static void deferred_type_access_control PARAMS ((void));
static void emit_associated_thunks PARAMS ((tree));
static void genrtl_try_block PARAMS ((tree));
static void genrtl_eh_spec_block PARAMS ((tree));
static void genrtl_handler PARAMS ((tree));
static void genrtl_catch_block PARAMS ((tree));
static void genrtl_ctor_stmt PARAMS ((tree));
@ -575,14 +576,14 @@ genrtl_try_block (t)
{
expand_eh_region_start ();
expand_stmt (TRY_STMTS (t));
expand_eh_region_end (protect_with_terminate (TRY_HANDLERS (t)));
expand_eh_region_end_cleanup (TRY_HANDLERS (t));
}
else
{
if (!FN_TRY_BLOCK_P (t))
emit_line_note (input_filename, lineno);
expand_start_try_stmts ();
expand_eh_region_start ();
expand_stmt (TRY_STMTS (t));
if (FN_TRY_BLOCK_P (t))
@ -603,6 +604,21 @@ genrtl_try_block (t)
}
}
/* Generate the RTL for T, which is an EH_SPEC_BLOCK. */
static void
genrtl_eh_spec_block (t)
tree t;
{
expand_eh_region_start ();
expand_stmt (EH_SPEC_STMTS (t));
expand_eh_region_end_allowed (EH_SPEC_RAISES (t),
build_call (call_unexpected_node,
tree_cons (NULL_TREE,
build_exc_ptr (),
NULL_TREE)));
}
/* Begin a try-block. Returns a newly-created TRY_BLOCK if
appropriate. */
@ -706,13 +722,7 @@ genrtl_handler (t)
genrtl_do_pushlevel ();
expand_stmt (HANDLER_BODY (t));
if (!processing_template_decl)
{
/* Fall to outside the try statement when done executing
handler and we fall off end of handler. This is jump
Lresume in the documentation. */
expand_goto (top_label_entry (&caught_return_label_stack));
end_catch_handler ();
}
expand_end_catch ();
}
/* Begin a handler. Returns a HANDLER if appropriate. */
@ -757,13 +767,13 @@ finish_handler_parms (decl, handler)
return blocks;
}
/* Generate the RTL for a CATCH_BLOCK. */
/* Generate the RTL for a START_CATCH_STMT. */
static void
genrtl_catch_block (type)
tree type;
{
start_catch_handler (type);
expand_start_catch (type);
}
/* Note the beginning of a handler for TYPE. This function is called
@ -2209,6 +2219,10 @@ cp_expand_stmt (t)
genrtl_try_block (t);
break;
case EH_SPEC_BLOCK:
genrtl_eh_spec_block (t);
break;
case HANDLER:
genrtl_handler (t);
break;
@ -2615,9 +2629,6 @@ genrtl_finish_function (fn)
&& ! DECL_NAME (DECL_RESULT (current_function_decl)))
no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
if (flag_exceptions)
expand_exception_blocks ();
/* If this function is supposed to return a value, ensure that
we do not fall into the cleanups by mistake. The end of our
function will look like this:

View File

@ -1037,6 +1037,7 @@ cp_statement_code_p (code)
case RETURN_INIT:
case TRY_BLOCK:
case HANDLER:
case EH_SPEC_BLOCK:
return 1;
default:

View File

@ -60,15 +60,15 @@ Boston, MA 02111-1307, USA. */
#include "auto-host.h"
#include "tconfig.h"
#include "tsystem.h"
#include "frame.h"
#include "unwind-dw2-fde.h"
#ifndef CRT_CALL_STATIC_FUNCTION
# define CRT_CALL_STATIC_FUNCTION(func) func ()
#endif
/* We do not want to add the weak attribute to the declarations of these
routines in frame.h because that will cause the definition of these
symbols to be weak as well.
routines in unwind-dw2-fde.h because that will cause the definition of
these symbols to be weak as well.
This exposes a core issue, how to handle creating weak references vs
how to create weak definitions. Either we have to have the definition

View File

@ -501,9 +501,14 @@ enum dwarf_call_frame_info
DW_CFA_def_cfa_offset = 0x0e,
DW_CFA_def_cfa_expression = 0x0f,
DW_CFA_expression = 0x10,
/* Dwarf 2.1 */
DW_CFA_offset_extended_sf = 0x11,
DW_CFA_def_cfa_sf = 0x12,
DW_CFA_def_cfa_offset_sf = 0x13,
/* SGI/MIPS specific */
DW_CFA_MIPS_advance_loc8 = 0x1d,
/* GNU extensions */
DW_CFA_GNU_window_save = 0x2d,
DW_CFA_GNU_args_size = 0x2e,
@ -554,3 +559,26 @@ enum dwarf_macinfo_record_type
DW_MACINFO_end_file = 4,
DW_MACINFO_vendor_ext = 255
};
/* @@@ For use with GNU frame unwind information. */
#define DW_EH_PE_absptr 0x00
#define DW_EH_PE_omit 0xff
#define DW_EH_PE_uleb128 0x01
#define DW_EH_PE_udata2 0x02
#define DW_EH_PE_udata4 0x03
#define DW_EH_PE_udata8 0x04
#define DW_EH_PE_sleb128 0x09
#define DW_EH_PE_sdata2 0x0A
#define DW_EH_PE_sdata4 0x0B
#define DW_EH_PE_sdata8 0x0C
#define DW_EH_PE_signed 0x08
#define DW_EH_PE_pcrel 0x10
#define DW_EH_PE_textrel 0x20
#define DW_EH_PE_datarel 0x30
#define DW_EH_PE_funcrel 0x40
#define DW_EH_PE_indirect 0x80

View File

@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA. */
#include "regs.h"
#include "insn-config.h"
#include "reload.h"
#include "function.h"
#include "output.h"
#include "expr.h"
#include "except.h"
@ -150,7 +151,9 @@ typedef struct dw_fde_struct
const char *dw_fde_current_label;
const char *dw_fde_end;
dw_cfi_ref dw_fde_cfi;
int nothrow;
unsigned funcdef_number;
unsigned nothrow : 1;
unsigned uses_eh_lsda : 1;
}
dw_fde_node;
@ -217,7 +220,7 @@ static dw_cfi_ref cie_cfi_head;
maximum number of function definitions contained within the current
compilation unit. These numbers are used to create unique label id's
unique to each function definition. */
static unsigned current_funcdef_number = 0;
unsigned current_funcdef_number = 0;
/* Some DWARF extensions (e.g., MIPS/SGI) implement a subprogram
attribute that accelerates the lookup of the FDE associated
@ -1684,22 +1687,22 @@ output_call_frame_info (for_eh)
register dw_fde_ref fde;
register dw_cfi_ref cfi;
char l1[20], l2[20];
#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
char ld[20];
#endif
/* Do we want to include a pointer to the exception table? */
int eh_ptr = for_eh && exception_table_p ();
int any_lsda_needed = 0;
char augmentation[6];
/* If we don't have any functions we'll want to unwind out of, don't
emit any EH unwind information. */
if (for_eh)
{
int any_eh_needed = 0;
for (i = 0; i < fde_table_in_use; ++i)
if (! fde_table[i].nothrow)
goto found;
return;
found:;
if (fde_table[i].uses_eh_lsda)
any_eh_needed = any_lsda_needed = 1;
else if (! fde_table[i].nothrow)
any_eh_needed = 1;
if (! any_eh_needed)
return;
}
/* We're going to be generating comments, so turn on app. */
@ -1726,14 +1729,8 @@ output_call_frame_info (for_eh)
/* Output the CIE. */
ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh);
ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh);
#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
ASM_GENERATE_INTERNAL_LABEL (ld, CIE_LENGTH_LABEL, for_eh);
dw2_asm_output_offset (for_eh ? 4 : DWARF_OFFSET_SIZE, ld,
"Length of Common Information Entry");
#else
dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
"Length of Common Information Entry");
#endif
ASM_OUTPUT_LABEL (asm_out_file, l1);
/* Now that the CIE pointer is PC-relative for EH,
@ -1744,20 +1741,23 @@ output_call_frame_info (for_eh)
dw2_asm_output_data (1, DW_CIE_VERSION, "CIE Version");
if (eh_ptr)
augmentation[0] = 0;
if (for_eh)
{
/* The CIE contains a pointer to the exception region info for the
frame. Make the augmentation string three bytes (including the
trailing null) so the pointer is 4-byte aligned. The Solaris ld
can't handle unaligned relocs. */
dw2_asm_output_nstring ("eh", -1, "CIE Augmentation");
dw2_asm_output_addr (DWARF2_ADDR_SIZE, "__EXCEPTION_TABLE__",
"pointer to exception region info");
}
else
{
dw2_asm_output_data (1, 0, "CIE Augmentation (none)");
/* Augmentation:
z Indicates that a uleb128 is present to size the
augmentation section.
R Indicates a pointer encoding for CIE and FDE pointers.
P Indicates the presence of a language personality
routine in the CIE augmentation and an LSDA in the
FDE augmentation. */
/* ??? Handle pointer encodings. */
if (any_lsda_needed)
strcpy (augmentation, "zP");
}
dw2_asm_output_nstring (augmentation, -1, "CIE Augmentation");
dw2_asm_output_data_uleb128 (1, "CIE Code Alignment Factor");
@ -1766,38 +1766,37 @@ output_call_frame_info (for_eh)
dw2_asm_output_data (1, DWARF_FRAME_RETURN_COLUMN, "CIE RA Column");
if (augmentation[0])
{
dw2_asm_output_data_uleb128 (DWARF2_ADDR_SIZE, "Augmentation size");
if (eh_personality_libfunc)
dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, eh_personality_libfunc,
"Personality");
else
dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, "Personality (none)");
}
for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
output_cfi (cfi, NULL);
/* Pad the CIE out to an address sized boundary. */
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DWARF2_ADDR_SIZE));
ASM_OUTPUT_LABEL (asm_out_file, l2);
#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL (asm_out_file, ld, l2, l1);
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s CIE Length Symbol", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
#endif
/* Loop through all of the FDE's. */
for (i = 0; i < fde_table_in_use; ++i)
{
fde = &fde_table[i];
/* Don't emit EH unwind info for leaf functions. */
if (for_eh && fde->nothrow)
/* Don't emit EH unwind info for leaf functions that don't need it. */
if (for_eh && fde->nothrow && ! fde->uses_eh_lsda)
continue;
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, FDE_LABEL, for_eh + i * 2);
ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i * 2);
ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i * 2);
#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
ASM_GENERATE_INTERNAL_LABEL (ld, FDE_LENGTH_LABEL, for_eh + i * 2);
dw2_asm_output_offset (for_eh ? 4 : DWARF_OFFSET_SIZE, ld, "FDE Length");
#else
dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
"FDE Length");
#endif
ASM_OUTPUT_LABEL (asm_out_file, l1);
/* ??? This always emits a 4 byte offset when for_eh is true, but it
@ -1821,6 +1820,21 @@ output_call_frame_info (for_eh)
dw2_asm_output_delta (DWARF2_ADDR_SIZE, fde->dw_fde_end,
fde->dw_fde_begin, "FDE address range");
if (augmentation[0])
{
dw2_asm_output_data_uleb128 (DWARF2_ADDR_SIZE, "Augmentation size");
if (fde->uses_eh_lsda)
{
ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA", fde->funcdef_number);
dw2_asm_output_offset (DWARF2_ADDR_SIZE, l1,
"Language Specific Data Area");
}
else
dw2_asm_output_data (DWARF2_ADDR_SIZE, 0,
"Language Specific Data Area (none)");
}
/* Loop through the Call Frame Instructions associated with
this FDE. */
fde->dw_fde_current_label = fde->dw_fde_begin;
@ -1830,12 +1844,6 @@ output_call_frame_info (for_eh)
/* Pad the FDE out to an address sized boundary. */
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DWARF2_ADDR_SIZE));
ASM_OUTPUT_LABEL (asm_out_file, l2);
#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL (asm_out_file, ld, l2, l1);
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s FDE Length Symbol", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
#endif
}
#ifndef EH_FRAME_SECTION
@ -1888,7 +1896,9 @@ dwarf2out_begin_prologue ()
fde->dw_fde_current_label = NULL;
fde->dw_fde_end = NULL;
fde->dw_fde_cfi = NULL;
fde->funcdef_number = current_funcdef_number;
fde->nothrow = current_function_nothrow;
fde->uses_eh_lsda = cfun->uses_eh_lsda;
args_size = old_args_size = 0;
}

View File

@ -41,3 +41,5 @@ extern void debug_dwarf_die PARAMS ((struct die_struct *));
extern void dwarf2out_set_demangle_name_func PARAMS ((const char *(*) (const char *)));
extern void dwarf2out_abstract_function PARAMS ((tree));
extern void dwarf2out_add_library_unit_info PARAMS ((const char *, const char *));
extern unsigned current_funcdef_number;

View File

@ -1,162 +0,0 @@
/* EH stuff
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This file contains the structures required for the language
independent exception handling model. Both the static compiler and
the runtime library share this file. */
/* 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
on the results of a call to a matching function provided by the expcetion
thrower. Otherwise the old scheme of calling any handler which matches
an exception range is used, and the handler is responsible for all
checking of runtime conditions. If the handler wasn't suppose to
get the exception, it performs a re-throw. */
/* 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.
The routine get_dynamic_handler_chain() also has a dependancy on
the location of 'dynamic_handler_chain'. If its location is changed,
that routine must be modified as well. */
#ifndef EH_ALLOC_SIZE
/* 192 bytes means the entire eh_context plus malloc overhead fits in 256
bytes (assuming 8 byte pointers). 192 bytes gives an eh_info and object
size limit of 96 bytes. This should be sufficient for throwing bad_alloc. */
#define EH_ALLOC_SIZE 192
#endif
#ifndef EH_ALLOC_ALIGN
/* We can't use BIGGEST_ALIGNMENT, because on some systems, that expands to
a check on a compile time switch like
'target_flags & MASK_ALIGN_DOUBLE ? 64 : 32'. There's no macro for
'largest alignment for any code this compiler can build for', which is
really what is needed. */
#define EH_ALLOC_ALIGN 16
#endif
struct eh_context
{
void *handler_label;
void **dynamic_handler_chain;
/* This is language dependent part of the eh context. */
void *info;
/* This is used to remember where we threw for re-throws */
void *table_index; /* address of exception table entry to rethrow from */
/* emergency fallback space, if malloc fails during handling */
char alloc_buffer[EH_ALLOC_SIZE]
__attribute__((__aligned__(EH_ALLOC_ALIGN)));
unsigned alloc_mask;
};
#ifndef EH_TABLE_LOOKUP
typedef struct old_exception_table
{
void *start_region;
void *end_region;
void *exception_handler;
} old_exception_table;
typedef struct exception_table
{
void *start_region;
void *end_region;
void *exception_handler;
void *match_info; /* runtime type info */
} exception_table;
/* The language identifying portion of an exception table */
typedef struct exception_lang_info
{
short language;
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;
struct __eh_info; /* forward declaration */
/* A pointer to a matching function is initialized at runtime by the
specific language if run-time exceptions are supported.
The function takes 3 parameters
1 - runtime exception that has been thrown info. (__eh_info *)
2 - Match info pointer from the region being considered (void *)
3 - exception table region is in (exception descriptor *)
*/
typedef void * (*__eh_matcher) PARAMS ((struct __eh_info *, void *,
struct exception_descriptor *));
/* This value is to be checked as a 'match all' case in the runtime field. */
#define CATCH_ALL_TYPE ((void *) -1)
/* This is the runtime exception information. This forms the minimum required
information for an exception info pointer in an eh_context structure. */
typedef struct __eh_info
{
__eh_matcher match_function;
short language;
short version;
} __eh_info;
/* Convienient language codes for ID the originating language. Similar
to the codes in dwarf2.h. */
enum exception_source_language
{
EH_LANG_C89 = 0x0001,
EH_LANG_C = 0x0002,
EH_LANG_Ada83 = 0x0003,
EH_LANG_C_plus_plus = 0x0004,
EH_LANG_Cobol74 = 0x0005,
EH_LANG_Cobol85 = 0x0006,
EH_LANG_Fortran77 = 0x0007,
EH_LANG_Fortran90 = 0x0008,
EH_LANG_Pascal83 = 0x0009,
EH_LANG_Modula2 = 0x000a,
EH_LANG_Java = 0x000b,
EH_LANG_Mips_Assembler = 0x8001
};
#endif /* EH_TABLE_LOOKUP */

File diff suppressed because it is too large Load Diff

View File

@ -19,516 +19,187 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#if !defined(NULL_RTX) && !defined(rtx)
typedef struct rtx_def *_except_rtx;
#define rtx _except_rtx
#ifndef TREE_CODE
union tree_node;
#define tree union tree_node *
#endif
#ifdef TREE_CODE
/* A stack of labels. CHAIN points to the next entry in the stack. */
struct label_node {
union {
rtx rlabel;
tree tlabel;
} u;
struct label_node *chain;
};
/* An eh_entry is used to describe one exception handling region.
OUTER_CONTEXT is the label used for rethrowing into the outer context.
EXCEPTION_HANDLER_LABEL is the label corresponding to the handler
for this region.
LABEL_USED indicates whether a CATCH block has already used this
label or not. New ones are needed for additional catch blocks if
it has.
FALSE_LABEL is used when either setjmp/longjmp exceptions are in
use, or old style table exceptions. It contains the label for
branching to the next runtime type check as handlers are processed.
FINALIZATION is the tree codes for the handler, or is NULL_TREE if
one hasn't been generated yet, or is integer_zero_node to mark the
end of a group of try blocks. */
struct eh_entry {
rtx outer_context;
rtx exception_handler_label;
tree finalization;
int label_used;
rtx false_label;
rtx rethrow_label;
/* If non-zero, this entry is for a handler created when we left an
exception-region via goto. */
unsigned goto_entry_p : 1;
};
#else
struct label_node;
struct eh_entry;
#ifndef RTX_CODE
struct rtx_def;
#define rtx struct rtx_def *
#endif
/* A list of EH_ENTRYs. ENTRY is the entry; CHAIN points to the next
entry in the list, or is NULL if this is the last entry. */
struct eh_node {
struct eh_entry *entry;
struct eh_node *chain;
};
/* A stack of EH_ENTRYs. TOP is the topmost entry on the stack. TOP is
NULL if the stack is empty. */
struct eh_stack {
struct eh_node *top;
};
/* A queue of EH_ENTRYs. HEAD is the front of the queue; TAIL is the
end (the latest entry). HEAD and TAIL are NULL if the queue is
empty. */
struct eh_queue {
struct eh_node *head;
struct eh_node *tail;
struct eh_queue *next;
};
/* Used to save exception handling status for each function. */
struct eh_status
{
/* A stack used for keeping track of the currently active exception
handling region. As each exception region is started, an entry
describing the region is pushed onto this stack. The current
region can be found by looking at the top of the stack, and as we
exit regions, the corresponding entries are popped.
Entries cannot overlap; they can be nested. So there is only one
entry at most that corresponds to the current instruction, and that
is the entry on the top of the stack. */
struct eh_stack x_ehstack;
/* This stack is used to represent what the current eh region is
for the catch blocks beings processed */
struct eh_stack x_catchstack;
/* A queue used for tracking which exception regions have closed.
As we exit a region, we enqueue a new entry. The entries are then
dequeued during expand_leftover_cleanups and
expand_start_all_catch. */
struct eh_queue *x_ehqueue;
/* Insns for all of the exception handlers for the current function.
They are currently emitted by the frontend code. */
rtx x_catch_clauses;
/* End of exception handler insn sequence. */
rtx x_catch_clauses_last;
/* A random data area for the front end's own use. */
struct label_node *x_false_label_stack;
/* Keeps track of the label to resume to should one want to resume
normal control flow out of a handler (instead of, say, returning to
the caller of the current function or exiting the program). */
struct label_node *x_caught_return_label_stack;
/* A stack (TREE_LIST) of lists of handlers. The TREE_VALUE of each
node is itself a TREE_CHAINed list of handlers for regions that
are not yet closed. The TREE_VALUE of each entry contains the
handler for the corresponding entry on the ehstack. */
union tree_node *x_protect_list;
/* The EH context. Nonzero if the function has already
fetched a pointer to the EH context for exception handling. */
rtx ehc;
/* The label generated by expand_builtin_eh_return. */
rtx x_eh_return_stub_label;
};
#define ehstack (cfun->eh->x_ehstack)
#define catchstack (cfun->eh->x_catchstack)
#define ehqueue (cfun->eh->x_ehqueue)
#define catch_clauses (cfun->eh->x_catch_clauses)
#define catch_clauses_last (cfun->eh->x_catch_clauses_last)
#define false_label_stack (cfun->eh->x_false_label_stack)
#define caught_return_label_stack (cfun->eh->x_caught_return_label_stack)
#define protect_list (cfun->eh->x_protect_list)
#define current_function_ehc (cfun->eh->ehc)
#define eh_return_stub_label (cfun->eh->x_eh_return_stub_label)
#ifdef TREE_CODE
/* Start an exception handling region. All instructions emitted after
this point are considered to be part of the region until
expand_eh_region_end () is invoked. */
extern void expand_eh_region_start PARAMS ((void));
/* Just like expand_eh_region_start, except if a cleanup action is
entered on the cleanup chain, the TREE_PURPOSE of the element put
on the chain is DECL. DECL should be the associated VAR_DECL, if
any, otherwise it should be NULL_TREE. */
extern void expand_eh_region_start_for_decl PARAMS ((tree));
/* Start an exception handling region for the given cleanup action.
All instructions emitted after this point are considered to be part
of the region until expand_eh_region_end () is invoked. CLEANUP is
the cleanup action to perform. The return value is true if the
exception region was optimized away. If that case,
expand_eh_region_end does not need to be called for this cleanup,
nor should it be.
This routine notices one particular common case in C++ code
generation, and optimizes it so as to not need the exception
region. */
extern int expand_eh_region_start_tree PARAMS ((tree, tree));
/* End an exception handling region. The information about the region
is found on the top of ehstack.
HANDLER is either the cleanup for the exception region, or if we're
marking the end of a try block, HANDLER is integer_zero_node.
HANDLER will be transformed to rtl when expand_leftover_cleanups ()
is invoked. */
extern void expand_eh_region_end PARAMS ((tree));
/* Push RLABEL or TLABEL onto LABELSTACK. Only one of RLABEL or TLABEL
should be set; the other must be NULL. */
extern void push_label_entry PARAMS ((struct label_node **labelstack,
rtx rlabel, tree tlabel));
/* Pop the topmost entry from LABELSTACK and return its value as an
rtx node. If LABELSTACK is empty, return NULL. */
extern rtx pop_label_entry PARAMS ((struct label_node **labelstack));
/* Return the topmost entry of LABELSTACK as a tree node, or return
NULL_TREE if LABELSTACK is empty. */
extern tree top_label_entry PARAMS ((struct label_node **labelstack));
#ifndef _VARRAY_H_
struct varray_head_tag;
#define varray_type struct varray_head_tag *
#endif
/* Test: is exception handling turned on? */
/* Per-function EH data. Used only in except.c, but GC and others
manipulate pointers to the opaque type. */
struct eh_status;
/* Internal structure describing a region. */
struct eh_region;
/* Test: is exception handling turned on? */
extern int doing_eh PARAMS ((int));
/* Toplevel initialization for EH. */
/* Start an exception handling region. All instructions emitted after
this point are considered to be part of the region until an
expand_eh_region_end variant is invoked. */
extern void expand_eh_region_start PARAMS ((void));
void set_exception_lang_code PARAMS ((int));
void set_exception_version_code PARAMS ((int));
/* 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
means This is a cleanup, and must always be called. A value of
CATCH_ALL_TYPE works like a cleanup, but a call to the runtime matcher
is still performed to avoid being caught by a different language
exception. NEXT is a pointer to the next handler for this region.
NULL means there are no more. */
typedef struct handler_info
{
rtx handler_label;
int handler_number;
void *type_info;
struct handler_info *next;
} handler_info;
/* Add new handler information to an exception range. The first parameter
specifies the range number (returned from new_eh_entry()). The second
parameter specifies the handler. By default the handler is inserted at
the end of the list. A handler list may contain only ONE NULL_TREE
typeinfo entry. Regardless where it is positioned, a NULL_TREE entry
is always output as the LAST handler in the exception table for a region. */
void add_new_handler PARAMS ((int, struct handler_info *));
/* Remove a handler label. The handler label is being deleted, so all
regions which reference this handler should have it removed from their
list of possible handlers. Any region which has the final handler
removed can be deleted. */
void remove_handler PARAMS ((rtx));
/* Create a new handler structure initialized with the handler label and
typeinfo fields passed in. */
struct handler_info *get_new_handler PARAMS ((rtx, void *));
/* Make a duplicate of an exception region by copying all the handlers
for an exception region. Return the new handler index. */
int duplicate_eh_handlers PARAMS ((int, int, rtx (*)(rtx)));
/* map symbol refs for rethrow */
rtx rethrow_symbol_map PARAMS ((rtx, rtx (*)(rtx)));
/* Is the rethrow label for a region used? */
int rethrow_used PARAMS ((int));
/* Update the rethrow references to reflect rethrows which have been
optimized away. */
void update_rethrow_references PARAMS ((void));
/* Get a pointer to the first handler in an exception region's list. */
struct handler_info *get_first_handler PARAMS ((int));
/* Find all the runtime handlers type matches currently referenced */
int find_all_handler_type_matches PARAMS ((void ***));
/* The eh_nesting_info structure is used to find a list of valid handlers
for any arbitrary exception region. When init_eh_nesting_info is called,
the information is all pre-calculated and entered in this structure.
REGION_INDEX is a vector over all possible region numbers. Since the
number of regions is typically much smaller than the range of block
numbers, this is a sparse vector and the other data structures are
represented as dense vectors. Indexed with an exception region number, this
returns the index to use in the other data structures to retreive the
correct information.
HANDLERS is an array of vectors which point to handler_info structures.
when indexed, it gives the list of all possible handlers which can
be reached by a throw from this exception region.
NUM_HANDLERS is the equivilent array indicating how many handler
pointers there are in the HANDLERS vector.
OUTER_INDEX indicates which index represents the information for the
outer block. 0 indicates there is no outer context.
REGION_COUNT is the number of regions. */
typedef struct eh_nesting
{
int *region_index;
handler_info ***handlers;
int *num_handlers;
int *outer_index;
int region_count;
} eh_nesting_info;
/* Initialize the eh_nesting_info structure. */
eh_nesting_info *init_eh_nesting_info PARAMS ((void));
/* Get a list of handlers reachable from a an exception region/insn. */
int reachable_handlers PARAMS ((int, eh_nesting_info *, rtx,
handler_info ***handlers));
/* Free the eh_nesting_info structure. */
void free_eh_nesting_info PARAMS ((eh_nesting_info *));
extern void init_eh PARAMS ((void));
/* Initialization for the per-function EH data. */
extern void init_eh_for_function PARAMS ((void));
/* Generate an exception label. Use instead of gen_label_rtx */
extern rtx gen_exception_label PARAMS ((void));
/* Adds an EH table entry for EH entry number N. Called from
final_scan_insn for NOTE_INSN_EH_REGION_BEG. */
extern void add_eh_table_entry PARAMS ((int n));
/* Start a catch clause, triggered by runtime value paramter. */
#ifdef TREE_CODE
extern void start_catch_handler PARAMS ((tree));
#endif
/* End an individual catch clause. */
extern void end_catch_handler PARAMS ((void));
/* Returns a non-zero value if we need to output an exception table. */
extern int exception_table_p PARAMS ((void));
/* Outputs the exception table if we have one. */
extern void output_exception_table PARAMS ((void));
extern void output_exception_table_data PARAMS ((void));
/* Free the exception table. */
extern void free_exception_table PARAMS((void));
/* Used by the ia64 unwind format to output data for an individual
function. */
extern void output_function_exception_table PARAMS((void));
/* Given a return address in ADDR, determine the address we should use
to find the corresponding EH region. */
extern rtx eh_outer_context PARAMS ((rtx addr));
/* Called at the start of a block of try statements for which there is
a supplied catch handler. */
extern void expand_start_try_stmts PARAMS ((void));
/* Called at the start of a block of catch statements. It terminates the
previous set of try statements. */
/* End an exception handling region for a cleanup. HANDLER is an
expression to expand for the cleanup. */
extern void expand_eh_region_end_cleanup PARAMS ((tree));
/* End an exception handling region for a try block, and prepares
for subsequent calls to expand_start_catch. */
extern void expand_start_all_catch PARAMS ((void));
/* Called at the end of a block of catch statements. */
/* Begin a catch clause. TYPE is an object to be matched by the
runtime, or null if this is a catch-all clause. */
extern void expand_start_catch PARAMS ((tree));
/* End a catch clause. Control will resume after the try/catch block. */
extern void expand_end_catch PARAMS ((void));
/* End a sequence of catch handlers for a try block. */
extern void expand_end_all_catch PARAMS ((void));
/* End an exception region for an exception type filter. ALLOWED is a
TREE_LIST of TREE_VALUE objects to be matched by the runtime.
FAILURE is a function to invoke if a mismatch ocurrs. */
extern void expand_eh_region_end_allowed PARAMS ((tree, tree));
/* End an exception region for a must-not-throw filter. FAILURE is a
function to invoke if an uncaught exception propagates this far. */
extern void expand_eh_region_end_must_not_throw PARAMS ((tree));
/* End an exception region for a throw. No handling goes on here,
but it's the easiest way for the front-end to indicate what type
is being thrown. */
extern void expand_eh_region_end_throw PARAMS ((tree));
/* End a fixup region. Within this region the cleanups for the immediately
enclosing region are _not_ run. This is used for goto cleanup to avoid
destroying an object twice. */
extern void expand_eh_region_end_fixup PARAMS ((tree));
/* Begin a region that will contain entries created with
add_partial_entry. */
extern void begin_protect_partials PARAMS ((void));
#ifdef TREE_CODE
/* Create a new exception region and add the handler for the region
onto a list. These regions will be ended (and their handlers
emitted) when end_protect_partials is invoked. */
extern void add_partial_entry PARAMS ((tree handler));
#endif
onto a list. These regions will be ended (and their handlers emitted)
when end_protect_partials is invoked. */
extern void add_partial_entry PARAMS ((tree));
/* End all of the pending exception regions that have handlers added with
push_protect_entry (). */
add_partial_entry. */
extern void end_protect_partials PARAMS ((void));
/* An internal throw. */
extern void expand_internal_throw PARAMS ((void));
/* Called from expand_exception_blocks and expand_end_catch_block to
expand and pending handlers. */
extern void expand_leftover_cleanups PARAMS ((void));
/* If necessary, emit insns to get EH context for the current
function. */
extern void emit_eh_context PARAMS ((void));
/* Builds a list of handler labels and puts them in the global
variable exception_handler_labels. */
extern void find_exception_handler_labels PARAMS ((void));
/* Determine if an arbitrary label is an exception label */
extern int is_exception_handler_label PARAMS ((int));
/* Performs sanity checking on the check_exception_handler_labels
list. */
extern void check_exception_handler_labels PARAMS ((void));
/* Keeps track of the label used as the context of a throw to rethrow an
exception to the outer exception region. */
extern struct label_node *outer_context_label_stack;
/* A list of labels used for exception handlers. It is created by
find_exception_handler_labels for the optimization passes. */
/* A list of labels used for exception handlers. */
extern rtx exception_handler_labels;
/* Determine if the given INSN can throw an exception. */
extern int can_throw_internal PARAMS ((rtx));
extern bool can_throw_internal PARAMS ((rtx));
extern bool can_throw_external PARAMS ((rtx));
/* Return nonzero if nothing in this function can throw. */
extern bool nothrow_function_p PARAMS ((void));
extern int nothrow_function_p PARAMS ((void));
/* After initial rtl generation, call back to finish generating
exception support code. */
extern void finish_eh_generation PARAMS ((void));
/* Performs optimizations for exception handling, such as removing
unnecessary exception regions. Invoked from jump_optimize (). */
extern void init_eh PARAMS ((void));
extern void init_eh_for_function PARAMS ((void));
extern void exception_optimize PARAMS ((void));
extern rtx reachable_handlers PARAMS ((rtx));
extern void maybe_remove_eh_handler PARAMS ((rtx));
/* Return EH context (and set it up once per fn). */
extern rtx get_eh_context PARAMS ((void));
extern void convert_from_eh_region_ranges PARAMS ((void));
extern void convert_to_eh_region_ranges PARAMS ((void));
extern void find_exception_handler_labels PARAMS ((void));
extern void output_function_exception_table PARAMS ((void));
/* Get the dynamic handler chain. */
extern rtx get_dynamic_handler_chain PARAMS ((void));
extern void expand_builtin_unwind_init PARAMS ((void));
extern rtx expand_builtin_eh_return_data_regno PARAMS ((tree));
extern rtx expand_builtin_extract_return_addr PARAMS ((tree));
extern rtx expand_builtin_frob_return_addr PARAMS ((tree));
extern void expand_builtin_eh_return PARAMS ((tree, tree));
extern void expand_eh_return PARAMS ((void));
/* Get the dynamic cleanup chain. */
extern rtx get_dynamic_cleanup_chain PARAMS ((void));
extern rtx get_exception_pointer PARAMS ((void));
/* Throw an exception. */
struct function;
struct inline_remap;
extern int duplicate_eh_regions PARAMS ((struct function *,
struct inline_remap *));
extern void emit_throw PARAMS ((void));
extern void sjlj_emit_function_exit_after PARAMS ((rtx));
/* Save away the current ehqueue. */
extern void push_ehqueue PARAMS ((void));
/* Restore a previously pushed ehqueue. */
extern void pop_ehqueue PARAMS ((void));
/* Nonzero to protect cleanup actions with must-not-throw regions. */
extern tree protect_cleanup_actions;
/* One to protect cleanup actions with a handler that calls
__terminate, zero otherwise. */
/* Return true if type A catches type B. */
int (*lang_eh_type_covers) PARAMS ((tree a, tree b));
extern int protect_cleanup_actions_with_terminate;
/* Map a type to a runtime object to match type. */
tree (*lang_eh_runtime_type) PARAMS ((tree));
#ifdef TREE_CODE
extern tree protect_with_terminate PARAMS ((tree));
#ifndef TREE_CODE
#undef tree
#endif
extern void expand_fixup_region_start PARAMS ((void));
#ifdef TREE_CODE
extern void expand_fixup_region_end PARAMS ((tree));
#endif
/* Various hooks for the DWARF 2 __throw routine. */
void expand_builtin_unwind_init PARAMS ((void));
rtx expand_builtin_dwarf_fp_regnum PARAMS ((void));
#ifdef TREE_CODE
rtx expand_builtin_frob_return_addr PARAMS ((tree));
rtx expand_builtin_extract_return_addr PARAMS ((tree));
void expand_builtin_init_dwarf_reg_sizes PARAMS ((tree));
void expand_builtin_eh_return PARAMS ((tree, tree, tree));
#endif
void expand_eh_return PARAMS ((void));
/* Checking whether 2 instructions are within the same exception region. */
int in_same_eh_region PARAMS ((rtx, rtx));
void free_insn_eh_region PARAMS ((void));
void init_insn_eh_region PARAMS ((rtx, int));
#ifdef rtx
#ifndef RTX_CODE
#undef rtx
#endif
#ifndef _VARRAY_H_
#undef varray_type
#endif
/* Just because the user configured --with-sjlj-exceptions=no doesn't
mean that we can use call frame exceptions. Detect that the target
has appropriate support. */
#if !defined (EH_RETURN_DATA_REGNO) \
|| !defined(EH_RETURN_STACKADJ_RTX) \
|| ! (defined(EH_RETURN_HANDLER_RTX) \
|| defined(HAVE_eh_return)) \
|| ! (defined(DWARF2_UNWIND_INFO) \
|| defined(IA64_UNWIND_INFO))
#define MUST_USE_SJLJ_EXCEPTIONS 1
#else
#define MUST_USE_SJLJ_EXCEPTIONS 0
#endif
#ifdef CONFIG_SJLJ_EXCEPTIONS
# if CONFIG_SJLJ_EXCEPTIONS == 1
# define USING_SJLJ_EXCEPTIONS 1
# endif
# if CONFIG_SJLJ_EXCEPTIONS == 0
# define USING_SJLJ_EXCEPTIONS 0
# ifndef EH_RETURN_DATA_REGNO
#error "EH_RETURN_DATA_REGNO required"
# endif
# ifndef EH_RETURN_STACKADJ_RTX
#error "EH_RETURN_STACKADJ_RTX required"
# endif
# if !defined(EH_RETURN_HANDLER_RTX) && !defined(HAVE_eh_return)
#error "EH_RETURN_HANDLER_RTX or eh_return required"
# endif
# if !defined(DWARF2_UNWIND_INFO) && !defined(IA64_UNWIND_INFO)
#error "{DWARF2,IA64}_UNWIND_INFO required"
# endif
# endif
#else
# ifdef IA64_UNWIND_INFO
# define USING_SJLJ_EXCEPTIONS (!IA64_UNWIND_INFO)
# else
# ifdef DWARF2_UNWIND_INFO
# define USING_SJLJ_EXCEPTIONS (!DWARF2_UNWIND_INFO)
# endif
# endif
# define USING_SJLJ_EXCEPTIONS MUST_USE_SJLJ_EXCEPTIONS
#endif

View File

@ -8741,7 +8741,7 @@ expand_expr (exp, target, tmode, modifier)
op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
expand_eh_region_end (handler);
expand_eh_region_end_cleanup (handler);
return op0;
}
@ -8788,23 +8788,12 @@ expand_expr (exp, target, tmode, modifier)
return const0_rtx;
}
case POPDCC_EXPR:
{
rtx dcc = get_dynamic_cleanup_chain ();
emit_move_insn (dcc, validize_mem (gen_rtx_MEM (Pmode, dcc)));
return const0_rtx;
}
case POPDHC_EXPR:
{
rtx dhc = get_dynamic_handler_chain ();
emit_move_insn (dhc, validize_mem (gen_rtx_MEM (Pmode, dhc)));
return const0_rtx;
}
case VA_ARG_EXPR:
return expand_builtin_va_arg (TREE_OPERAND (exp, 0), type);
case EXC_PTR_EXPR:
return get_exception_pointer ();
default:
return (*lang_expand_expr) (exp, original_target, tmode, modifier);
}

View File

@ -495,14 +495,12 @@ enum libfunc_index
LTI_memset,
LTI_bzero,
LTI_throw,
LTI_rethrow,
LTI_sjthrow,
LTI_sjpopnthrow,
LTI_terminate,
LTI_unwind_resume,
LTI_eh_personality,
LTI_setjmp,
LTI_longjmp,
LTI_eh_rtime_match,
LTI_unwind_sjlj_register,
LTI_unwind_sjlj_unregister,
LTI_eqhf2,
LTI_nehf2,
@ -628,14 +626,13 @@ extern rtx libfunc_table[LTI_MAX];
#define memset_libfunc (libfunc_table[LTI_memset])
#define bzero_libfunc (libfunc_table[LTI_bzero])
#define throw_libfunc (libfunc_table[LTI_throw])
#define rethrow_libfunc (libfunc_table[LTI_rethrow])
#define sjthrow_libfunc (libfunc_table[LTI_sjthrow])
#define sjpopnthrow_libfunc (libfunc_table[LTI_sjpopnthrow])
#define terminate_libfunc (libfunc_table[LTI_terminate])
#define unwind_resume_libfunc (libfunc_table[LTI_unwind_resume])
#define eh_personality_libfunc (libfunc_table[LTI_eh_personality])
#define setjmp_libfunc (libfunc_table[LTI_setjmp])
#define longjmp_libfunc (libfunc_table[LTI_longjmp])
#define eh_rtime_match_libfunc (libfunc_table[LTI_eh_rtime_match])
#define unwind_sjlj_register_libfunc (libfunc_table[LTI_unwind_sjlj_register])
#define unwind_sjlj_unregister_libfunc \
(libfunc_table[LTI_unwind_sjlj_unregister])
#define eqhf2_libfunc (libfunc_table[LTI_eqhf2])
#define nehf2_libfunc (libfunc_table[LTI_nehf2])

View File

@ -1945,8 +1945,6 @@ final (first, file, optimize, prescan)
last_ignored_compare = 0;
new_block = 1;
check_exception_handler_labels ();
/* Make a map indicating which line numbers appear in this function.
When producing SDB debugging info, delete troublesome line number
notes from inlined functions in other files as well as duplicate
@ -2003,10 +2001,6 @@ final (first, file, optimize, prescan)
#endif
}
/* Initialize insn_eh_region table if eh is being used. */
init_insn_eh_region (first, max_uid);
init_recog ();
CC_STATUS_INIT;
@ -2040,7 +2034,6 @@ final (first, file, optimize, prescan)
if (profile_block_flag && new_block)
add_bb (file);
free_insn_eh_region ();
free (line_note_exists);
line_note_exists = NULL;
}
@ -2126,24 +2119,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
break;
case NOTE_INSN_EH_REGION_BEG:
if (! USING_SJLJ_EXCEPTIONS)
{
ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", NOTE_EH_HANDLER (insn));
#ifdef ASM_OUTPUT_EH_REGION_BEG
ASM_OUTPUT_EH_REGION_BEG (file, NOTE_EH_HANDLER (insn));
#endif
}
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHB",
NOTE_EH_HANDLER (insn));
break;
case NOTE_INSN_EH_REGION_END:
if (! USING_SJLJ_EXCEPTIONS)
{
ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", NOTE_EH_HANDLER (insn));
add_eh_table_entry (NOTE_EH_HANDLER (insn));
#ifdef ASM_OUTPUT_EH_REGION_END
ASM_OUTPUT_EH_REGION_END (file, NOTE_EH_HANDLER (insn));
#endif
}
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHE",
NOTE_EH_HANDLER (insn));
break;
case NOTE_INSN_PROLOGUE_END:

View File

@ -204,7 +204,6 @@ struct basic_block_def entry_exit_blocks[2]
NULL, /* aux */
ENTRY_BLOCK, /* index */
0, /* loop_depth */
-1, -1, /* eh_beg, eh_end */
0 /* count */
},
{
@ -219,7 +218,6 @@ struct basic_block_def entry_exit_blocks[2]
NULL, /* aux */
EXIT_BLOCK, /* index */
0, /* loop_depth */
-1, -1, /* eh_beg, eh_end */
0 /* count */
}
};
@ -368,16 +366,12 @@ static void clear_edges PARAMS ((void));
static void make_edges PARAMS ((rtx));
static void make_label_edge PARAMS ((sbitmap *, basic_block,
rtx, int));
static void make_eh_edge PARAMS ((sbitmap *, eh_nesting_info *,
basic_block, rtx, int));
static void make_eh_edge PARAMS ((sbitmap *, basic_block, rtx));
static void mark_critical_edges PARAMS ((void));
static void move_stray_eh_region_notes PARAMS ((void));
static void record_active_eh_regions PARAMS ((rtx));
static void commit_one_edge_insertion PARAMS ((edge));
static void delete_unreachable_blocks PARAMS ((void));
static void delete_eh_regions PARAMS ((void));
static int can_delete_note_p PARAMS ((rtx));
static void expunge_block PARAMS ((basic_block));
static int can_delete_label_p PARAMS ((rtx));
@ -537,7 +531,6 @@ find_basic_blocks (f, nregs, file)
compute_bb_for_insn (max_uid);
/* Discover the edges of our cfg. */
record_active_eh_regions (f);
make_edges (label_value_list);
/* Do very simple cleanup now, for the benefit of code that runs between
@ -599,46 +592,45 @@ count_basic_blocks (f)
register rtx insn;
register RTX_CODE prev_code;
register int count = 0;
int eh_region = 0;
int call_had_abnormal_edge = 0;
int saw_abnormal_edge = 0;
prev_code = JUMP_INSN;
for (insn = f; insn; insn = NEXT_INSN (insn))
{
register RTX_CODE code = GET_CODE (insn);
enum rtx_code code = GET_CODE (insn);
if (code == CODE_LABEL
|| (GET_RTX_CLASS (code) == 'i'
&& (prev_code == JUMP_INSN
|| prev_code == BARRIER
|| (prev_code == CALL_INSN && call_had_abnormal_edge))))
count++;
|| saw_abnormal_edge)))
{
saw_abnormal_edge = 0;
count++;
}
/* Record whether this call created an edge. */
/* Record whether this insn created an edge. */
if (code == CALL_INSN)
{
rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
int region = (note ? INTVAL (XEXP (note, 0)) : 1);
rtx note;
call_had_abnormal_edge = 0;
/* If there is a nonlocal goto label and the specified
region number isn't -1, we have an edge. */
if (nonlocal_goto_handler_labels
&& ((note = find_reg_note (insn, REG_EH_REGION, NULL_RTX)) == 0
|| INTVAL (XEXP (note, 0)) >= 0))
saw_abnormal_edge = 1;
/* If there is an EH region or rethrow, we have an edge. */
if ((eh_region && region > 0)
|| find_reg_note (insn, REG_EH_RETHROW, NULL_RTX))
call_had_abnormal_edge = 1;
else if (nonlocal_goto_handler_labels && region >= 0)
/* If there is a nonlocal goto label and the specified
region number isn't -1, we have an edge. (0 means
no throw, but might have a nonlocal goto). */
call_had_abnormal_edge = 1;
else if (can_throw_internal (insn))
saw_abnormal_edge = 1;
}
else if (flag_non_call_exceptions
&& code == INSN
&& can_throw_internal (insn))
saw_abnormal_edge = 1;
if (code != NOTE)
prev_code = code;
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
++eh_region;
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
--eh_region;
}
/* The rest of the compiler works a bit smoother when we don't have to
@ -672,9 +664,6 @@ find_label_refs (f, lvl)
Make a special exception for labels followed by an ADDR*VEC,
as this would be a part of the tablejump setup code.
Make a special exception for the eh_return_stub_label, which
we know isn't part of any otherwise visible control flow.
Make a special exception to registers loaded with label
values just before jump insns that use them. */
@ -683,9 +672,7 @@ find_label_refs (f, lvl)
{
rtx lab = XEXP (note, 0), next;
if (lab == eh_return_stub_label)
;
else if ((next = next_nonnote_insn (lab)) != NULL
if ((next = next_nonnote_insn (lab)) != NULL
&& GET_CODE (next) == JUMP_INSN
&& (GET_CODE (PATTERN (next)) == ADDR_VEC
|| GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
@ -815,7 +802,6 @@ find_basic_blocks_1 (f)
register rtx insn, next;
int i = 0;
rtx bb_note = NULL_RTX;
rtx eh_list = NULL_RTX;
rtx lvl = NULL_RTX;
rtx trll = NULL_RTX;
rtx head = NULL_RTX;
@ -839,22 +825,11 @@ find_basic_blocks_1 (f)
{
int kind = NOTE_LINE_NUMBER (insn);
/* Keep a LIFO list of the currently active exception notes. */
if (kind == NOTE_INSN_EH_REGION_BEG)
eh_list = alloc_INSN_LIST (insn, eh_list);
else if (kind == NOTE_INSN_EH_REGION_END)
{
rtx t = eh_list;
eh_list = XEXP (eh_list, 1);
free_INSN_LIST_node (t);
}
/* Look for basic block notes with which to keep the
basic_block_info pointers stable. Unthread the note now;
we'll put it back at the right place in create_basic_block.
Or not at all if we've already found a note in this block. */
else if (kind == NOTE_INSN_BASIC_BLOCK)
if (kind == NOTE_INSN_BASIC_BLOCK)
{
if (bb_note == NULL_RTX)
bb_note = insn;
@ -938,8 +913,7 @@ find_basic_blocks_1 (f)
{
/* Record whether this call created an edge. */
rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
int region = (note ? INTVAL (XEXP (note, 0)) : 1);
int call_has_abnormal_edge = 0;
int region = (note ? INTVAL (XEXP (note, 0)) : 0);
if (GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
{
@ -952,19 +926,10 @@ find_basic_blocks_1 (f)
trll = alloc_EXPR_LIST (0, XEXP (PATTERN (insn), 3), trll);
}
/* If there is an EH region or rethrow, we have an edge. */
if ((eh_list && region > 0)
|| find_reg_note (insn, REG_EH_RETHROW, NULL_RTX))
call_has_abnormal_edge = 1;
else if (nonlocal_goto_handler_labels && region >= 0)
/* If there is a nonlocal goto label and the specified
region number isn't -1, we have an edge. (0 means
no throw, but might have a nonlocal goto). */
call_has_abnormal_edge = 1;
/* A basic block ends at a call that can either throw or
do a non-local goto. */
if (call_has_abnormal_edge)
if ((nonlocal_goto_handler_labels && region >= 0)
|| can_throw_internal (insn))
{
new_bb_inclusive:
if (head == NULL_RTX)
@ -980,18 +945,21 @@ find_basic_blocks_1 (f)
}
/* Fall through. */
default:
if (GET_RTX_CLASS (code) == 'i')
{
if (head == NULL_RTX)
head = insn;
end = insn;
}
case INSN:
/* Non-call exceptions generate new blocks just like calls. */
if (flag_non_call_exceptions && can_throw_internal (insn))
goto new_bb_inclusive;
if (head == NULL_RTX)
head = insn;
end = insn;
break;
default:
abort ();
}
if (GET_RTX_CLASS (code) == 'i'
&& GET_CODE (insn) != JUMP_INSN)
if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
{
rtx note;
@ -1000,9 +968,6 @@ find_basic_blocks_1 (f)
Make a special exception for labels followed by an ADDR*VEC,
as this would be a part of the tablejump setup code.
Make a special exception for the eh_return_stub_label, which
we know isn't part of any otherwise visible control flow.
Make a special exception to registers loaded with label
values just before jump insns that use them. */
@ -1011,9 +976,7 @@ find_basic_blocks_1 (f)
{
rtx lab = XEXP (note, 0), next;
if (lab == eh_return_stub_label)
;
else if ((next = next_nonnote_insn (lab)) != NULL
if ((next = next_nonnote_insn (lab)) != NULL
&& GET_CODE (next) == JUMP_INSN
&& (GET_CODE (PATTERN (next)) == ADDR_VEC
|| GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
@ -1047,8 +1010,6 @@ void
cleanup_cfg ()
{
delete_unreachable_blocks ();
move_stray_eh_region_notes ();
record_active_eh_regions (get_insns ());
try_merge_blocks ();
mark_critical_edges ();
@ -1201,7 +1162,6 @@ make_edges (label_value_list)
rtx label_value_list;
{
int i;
eh_nesting_info *eh_nest_info = init_eh_nesting_info ();
sbitmap *edge_cache = NULL;
/* Assume no computed jump; revise as we create edges. */
@ -1241,9 +1201,13 @@ make_edges (label_value_list)
{
rtx tmp;
/* Recognize exception handling placeholders. */
if (GET_CODE (PATTERN (insn)) == RESX)
make_eh_edge (edge_cache, bb, insn);
/* Recognize a non-local goto as a branch outside the
current function. */
if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
else if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
;
/* ??? Recognize a tablejump and do the right thing. */
@ -1318,37 +1282,15 @@ make_edges (label_value_list)
EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
/* If this is a CALL_INSN, then mark it as reaching the active EH
handler for this CALL_INSN. If we're handling asynchronous
handler for this CALL_INSN. If we're handling non-call
exceptions then any insn can reach any of the active handlers.
Also mark the CALL_INSN as reaching any nonlocal goto handler. */
else if (code == CALL_INSN || flag_non_call_exceptions)
{
/* Add any appropriate EH edges. We do this unconditionally
since there may be a REG_EH_REGION or REG_EH_RETHROW note
on the call, and this needn't be within an EH region. */
make_eh_edge (edge_cache, eh_nest_info, bb, insn, bb->eh_end);
/* If we have asynchronous exceptions, do the same for *all*
exception regions active in the block. */
if (flag_non_call_exceptions
&& bb->eh_beg != bb->eh_end)
{
if (bb->eh_beg >= 0)
make_eh_edge (edge_cache, eh_nest_info, bb,
NULL_RTX, bb->eh_beg);
for (x = bb->head; x != bb->end; x = NEXT_INSN (x))
if (GET_CODE (x) == NOTE
&& (NOTE_LINE_NUMBER (x) == NOTE_INSN_EH_REGION_BEG
|| NOTE_LINE_NUMBER (x) == NOTE_INSN_EH_REGION_END))
{
int region = NOTE_EH_HANDLER (x);
make_eh_edge (edge_cache, eh_nest_info, bb,
NULL_RTX, region);
}
}
/* Add any appropriate EH edges. */
make_eh_edge (edge_cache, bb, insn);
if (code == CALL_INSN && nonlocal_goto_handler_labels)
{
@ -1369,14 +1311,6 @@ make_edges (label_value_list)
}
}
/* We know something about the structure of the function __throw in
libgcc2.c. It is the only function that ever contains eh_stub
labels. It modifies its return address so that the last block
returns to one of the eh_stub labels within it. So we have to
make additional edges in the flow graph. */
if (i + 1 == n_basic_blocks && eh_return_stub_label != 0)
make_label_edge (edge_cache, bb, eh_return_stub_label, EDGE_EH);
/* Find out if we can drop through to the next block. */
insn = next_nonnote_insn (insn);
if (!insn || (i + 1 == n_basic_blocks && force_fallthru))
@ -1391,7 +1325,6 @@ make_edges (label_value_list)
}
}
free_eh_nesting_info (eh_nest_info);
if (edge_cache)
sbitmap_vector_free (edge_cache);
}
@ -1479,115 +1412,21 @@ make_label_edge (edge_cache, src, label, flags)
/* Create the edges generated by INSN in REGION. */
static void
make_eh_edge (edge_cache, eh_nest_info, src, insn, region)
make_eh_edge (edge_cache, src, insn)
sbitmap *edge_cache;
eh_nesting_info *eh_nest_info;
basic_block src;
rtx insn;
int region;
{
handler_info **handler_list;
int num, is_call;
int is_call = (GET_CODE (insn) == CALL_INSN ? EDGE_ABNORMAL_CALL : 0);
rtx handlers, i;
is_call = (insn && GET_CODE (insn) == CALL_INSN ? EDGE_ABNORMAL_CALL : 0);
num = reachable_handlers (region, eh_nest_info, insn, &handler_list);
while (--num >= 0)
{
make_label_edge (edge_cache, src, handler_list[num]->handler_label,
EDGE_ABNORMAL | EDGE_EH | is_call);
}
}
handlers = reachable_handlers (insn);
/* EH_REGION notes appearing between basic blocks is ambiguous, and even
dangerous if we intend to move basic blocks around. Move such notes
into the following block. */
for (i = handlers; i; i = XEXP (i, 1))
make_label_edge (edge_cache, src, XEXP (i, 0),
EDGE_ABNORMAL | EDGE_EH | is_call);
static void
move_stray_eh_region_notes ()
{
int i;
basic_block b1, b2;
if (n_basic_blocks < 2)
return;
b2 = BASIC_BLOCK (n_basic_blocks - 1);
for (i = n_basic_blocks - 2; i >= 0; --i, b2 = b1)
{
rtx insn, next, list = NULL_RTX;
b1 = BASIC_BLOCK (i);
for (insn = NEXT_INSN (b1->end); insn != b2->head; insn = next)
{
next = NEXT_INSN (insn);
if (GET_CODE (insn) == NOTE
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
{
/* Unlink from the insn chain. */
NEXT_INSN (PREV_INSN (insn)) = next;
PREV_INSN (next) = PREV_INSN (insn);
/* Queue it. */
NEXT_INSN (insn) = list;
list = insn;
}
}
if (list == NULL_RTX)
continue;
/* Find where to insert these things. */
insn = b2->head;
if (GET_CODE (insn) == CODE_LABEL)
insn = NEXT_INSN (insn);
while (list)
{
next = NEXT_INSN (list);
add_insn_after (list, insn);
list = next;
}
}
}
/* Recompute eh_beg/eh_end for each basic block. */
static void
record_active_eh_regions (f)
rtx f;
{
rtx insn, eh_list = NULL_RTX;
int i = 0;
basic_block bb = BASIC_BLOCK (0);
for (insn = f; insn; insn = NEXT_INSN (insn))
{
if (bb->head == insn)
bb->eh_beg = (eh_list ? NOTE_EH_HANDLER (XEXP (eh_list, 0)) : -1);
if (GET_CODE (insn) == NOTE)
{
int kind = NOTE_LINE_NUMBER (insn);
if (kind == NOTE_INSN_EH_REGION_BEG)
eh_list = alloc_INSN_LIST (insn, eh_list);
else if (kind == NOTE_INSN_EH_REGION_END)
{
rtx t = XEXP (eh_list, 1);
free_INSN_LIST_node (eh_list);
eh_list = t;
}
}
if (bb->end == insn)
{
bb->eh_end = (eh_list ? NOTE_EH_HANDLER (XEXP (eh_list, 0)) : -1);
i += 1;
if (i == n_basic_blocks)
break;
bb = BASIC_BLOCK (i);
}
}
free_INSN_LIST_list (&handlers);
}
/* Identify critical edges and set the bits appropriately. */
@ -2223,7 +2062,6 @@ static void
delete_unreachable_blocks ()
{
basic_block *worklist, *tos;
int deleted_handler;
edge e;
int i, n;
@ -2261,10 +2099,9 @@ delete_unreachable_blocks ()
}
}
/* Delete all unreachable basic blocks. Count down so that we don't
interfere with the block renumbering that happens in flow_delete_block. */
deleted_handler = 0;
/* Delete all unreachable basic blocks. Count down so that we
don't interfere with the block renumbering that happens in
flow_delete_block. */
for (i = n - 1; i >= 0; --i)
{
@ -2274,46 +2111,14 @@ delete_unreachable_blocks ()
/* This block was found. Tidy up the mark. */
b->aux = NULL;
else
deleted_handler |= flow_delete_block (b);
flow_delete_block (b);
}
tidy_fallthru_edges ();
/* If we deleted an exception handler, we may have EH region begin/end
blocks to remove as well. */
if (deleted_handler)
delete_eh_regions ();
free (worklist);
}
/* Find EH regions for which there is no longer a handler, and delete them. */
static void
delete_eh_regions ()
{
rtx insn;
update_rethrow_references ();
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == NOTE)
{
if ((NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
|| (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
{
int num = NOTE_EH_HANDLER (insn);
/* A NULL handler indicates a region is no longer needed,
as long as its rethrow label isn't used. */
if (get_first_handler (num) == NULL && ! rethrow_used (num))
{
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
}
}
}
}
/* Return true if NOTE is not one of the ones that must be kept paired,
so that we may simply delete them. */
@ -2387,26 +2192,7 @@ flow_delete_block (b)
never_reached_warning (insn);
if (GET_CODE (insn) == CODE_LABEL)
{
rtx x, *prev = &exception_handler_labels;
for (x = exception_handler_labels; x; x = XEXP (x, 1))
{
if (XEXP (x, 0) == insn)
{
/* Found a match, splice this label out of the EH label list. */
*prev = XEXP (x, 1);
XEXP (x, 1) = NULL_RTX;
XEXP (x, 0) = NULL_RTX;
/* Remove the handler from all regions */
remove_handler (insn);
deleted_handler = 1;
break;
}
prev = &XEXP (x, 1);
}
}
maybe_remove_eh_handler (insn);
/* Include any jump table following the basic block. */
end = b->end;
@ -2804,7 +2590,6 @@ merge_blocks (e, b, c)
else
{
edge tmp_edge;
basic_block d;
int c_has_outgoing_fallthru;
int b_has_incoming_fallthru;
@ -2832,37 +2617,22 @@ merge_blocks (e, b, c)
break;
b_has_incoming_fallthru = (tmp_edge != NULL);
/* If B does not have an incoming fallthru, and the exception regions
match, then it can be moved immediately before C without introducing
or modifying jumps.
C can not be the first block, so we do not have to worry about
/* If B does not have an incoming fallthru, then it can be moved
immediately before C without introducing or modifying jumps.
C cannot be the first block, so we do not have to worry about
accessing a non-existent block. */
d = BASIC_BLOCK (c->index - 1);
if (! b_has_incoming_fallthru
&& d->eh_end == b->eh_beg
&& b->eh_end == c->eh_beg)
if (! b_has_incoming_fallthru)
return merge_blocks_move_predecessor_nojumps (b, c);
/* Otherwise, we're going to try to move C after B. Make sure the
exception regions match.
/* Otherwise, we're going to try to move C after B. If C does
not have an outgoing fallthru, then it can be moved
immediately after B without introducing or modifying jumps. */
if (! c_has_outgoing_fallthru)
return merge_blocks_move_successor_nojumps (b, c);
If B is the last basic block, then we must not try to access the
block structure for block B + 1. Luckily in that case we do not
need to worry about matching exception regions. */
d = (b->index + 1 < n_basic_blocks ? BASIC_BLOCK (b->index + 1) : NULL);
if (b->eh_end == c->eh_beg
&& (d == NULL || c->eh_end == d->eh_beg))
{
/* If C does not have an outgoing fallthru, then it can be moved
immediately after B without introducing or modifying jumps. */
if (! c_has_outgoing_fallthru)
return merge_blocks_move_successor_nojumps (b, c);
/* Otherwise, we'll need to insert an extra jump, and possibly
a new block to contain it. */
/* ??? Not implemented yet. */
}
/* Otherwise, we'll need to insert an extra jump, and possibly
a new block to contain it. */
/* ??? Not implemented yet. */
return 0;
}
@ -3502,14 +3272,44 @@ mark_regs_live_at_end (set)
if (global_regs[i] || EPILOGUE_USES (i))
SET_REGNO_REG_SET (set, i);
/* Mark all call-saved registers that we actaully used. */
if (HAVE_epilogue && reload_completed)
{
/* Mark all call-saved registers that we actually used. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (regs_ever_live[i] && ! call_used_regs[i] && ! LOCAL_REGNO (i))
SET_REGNO_REG_SET (set, i);
}
#ifdef EH_RETURN_DATA_REGNO
/* Mark the registers that will contain data for the handler. */
if (reload_completed && current_function_calls_eh_return)
for (i = 0; ; ++i)
{
unsigned regno = EH_RETURN_DATA_REGNO(i);
if (regno == INVALID_REGNUM)
break;
SET_REGNO_REG_SET (set, regno);
}
#endif
#ifdef EH_RETURN_STACKADJ_RTX
if ((! HAVE_epilogue || ! reload_completed)
&& current_function_calls_eh_return)
{
rtx tmp = EH_RETURN_STACKADJ_RTX;
if (tmp && REG_P (tmp))
mark_reg (tmp, set);
}
#endif
#ifdef EH_RETURN_HANDLER_RTX
if ((! HAVE_epilogue || ! reload_completed)
&& current_function_calls_eh_return)
{
rtx tmp = EH_RETURN_HANDLER_RTX;
if (tmp && REG_P (tmp))
mark_reg (tmp, set);
}
#endif
/* Mark function return value. */
diddle_return_value (mark_reg, set);
}
@ -4249,7 +4049,8 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
&& (flags & PROP_SCAN_DEAD_CODE)
&& (bb->succ == NULL
|| (bb->succ->succ_next == NULL
&& bb->succ->dest == EXIT_BLOCK_PTR)))
&& bb->succ->dest == EXIT_BLOCK_PTR
&& ! current_function_calls_eh_return)))
{
rtx insn, set;
for (insn = bb->end; insn != bb->head; insn = PREV_INSN (insn))
@ -6631,8 +6432,6 @@ dump_bb (bb, outf)
fprintf (outf, ";; Basic block %d, loop depth %d, count %d",
bb->index, bb->loop_depth, bb->count);
if (bb->eh_beg != -1 || bb->eh_end != -1)
fprintf (outf, ", eh regions %d/%d", bb->eh_beg, bb->eh_end);
putc ('\n', outf);
fputs (";; Predecessors: ", outf);

View File

@ -1,778 +0,0 @@
/* Subroutines needed for unwinding DWARF 2 format stack frame info
for exception handling. */
/* Compile this one with gcc. */
/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@cygnus.com>.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file into combinations with other programs,
and to distribute those combinations without any restriction coming
from the use of this file. (The General Public License restrictions
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combine
executable.)
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* It is incorrect to include config.h here, because this file is being
compiled for the target, and hence definitions concerning only the host
do not apply. */
#include "tconfig.h"
#include "tsystem.h"
#ifdef DWARF2_UNWIND_INFO
#include "dwarf2.h"
#include "frame.h"
#include "gthr.h"
#ifdef __GTHREAD_MUTEX_INIT
static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT;
#else
static __gthread_mutex_t object_mutex;
#endif
/* Don't use `fancy_abort' here even if config.h says to use it. */
#ifdef abort
#undef abort
#endif
/* Some types used by the DWARF 2 spec. */
typedef int sword __attribute__ ((mode (SI)));
typedef unsigned int uword __attribute__ ((mode (SI)));
typedef unsigned int uaddr __attribute__ ((mode (pointer)));
typedef int saddr __attribute__ ((mode (pointer)));
typedef unsigned char ubyte;
/* Terminology:
CIE - Common Information Element
FDE - Frame Descriptor Element
There is one per function, and it describes where the function code
is located, and what the register lifetimes and stack layout are
within the function.
The data structures are defined in the DWARF specfication, although
not in a very readable way (see LITERATURE).
Every time an exception is thrown, the code needs to locate the FDE
for the current function, and starts to look for exception regions
from that FDE. This works in a two-level search:
a) in a linear search, find the shared image (i.e. DLL) containing
the PC
b) using the FDE table for that shared object, locate the FDE using
binary search (which requires the sorting). */
/* The first few fields of a CIE. The CIE_id field is 0 for a CIE,
to distinguish it from a valid FDE. FDEs are aligned to an addressing
unit boundary, but the fields within are unaligned. */
struct dwarf_cie {
uword length;
sword CIE_id;
ubyte version;
char augmentation[0];
} __attribute__ ((packed, aligned (__alignof__ (void *))));
/* The first few fields of an FDE. */
struct dwarf_fde {
uword length;
sword CIE_delta;
void* pc_begin;
uaddr pc_range;
} __attribute__ ((packed, aligned (__alignof__ (void *))));
typedef struct dwarf_fde fde;
/* Objects to be searched for frame unwind info. */
static struct object *objects;
/* The information we care about from a CIE. */
struct cie_info {
char *augmentation;
void *eh_ptr;
int code_align;
int data_align;
unsigned ra_regno;
};
/* The current unwind state, plus a saved copy for DW_CFA_remember_state. */
struct frame_state_internal
{
struct frame_state s;
struct frame_state_internal *saved_state;
};
/* This is undefined below if we need it to be an actual function. */
#define init_object_mutex_once()
#if __GTHREADS
#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
/* Helper for init_object_mutex_once. */
static void
init_object_mutex (void)
{
__GTHREAD_MUTEX_INIT_FUNCTION (&object_mutex);
}
/* Call this to arrange to initialize the object mutex. */
#undef init_object_mutex_once
static void
init_object_mutex_once (void)
{
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
__gthread_once (&once, init_object_mutex);
}
#endif /* __GTHREAD_MUTEX_INIT_FUNCTION */
#endif /* __GTHREADS */
/* Decode the unsigned LEB128 constant at BUF into the variable pointed to
by R, and return the new value of BUF. */
static void *
decode_uleb128 (unsigned char *buf, unsigned *r)
{
unsigned shift = 0;
unsigned result = 0;
while (1)
{
unsigned byte = *buf++;
result |= (byte & 0x7f) << shift;
if ((byte & 0x80) == 0)
break;
shift += 7;
}
*r = result;
return buf;
}
/* Decode the signed LEB128 constant at BUF into the variable pointed to
by R, and return the new value of BUF. */
static void *
decode_sleb128 (unsigned char *buf, int *r)
{
unsigned shift = 0;
unsigned result = 0;
unsigned byte;
while (1)
{
byte = *buf++;
result |= (byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
break;
}
if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
result |= - (1 << shift);
*r = result;
return buf;
}
/* Read unaligned data from the instruction buffer. */
union unaligned {
void *p;
unsigned b2 __attribute__ ((mode (HI)));
unsigned b4 __attribute__ ((mode (SI)));
unsigned b8 __attribute__ ((mode (DI)));
} __attribute__ ((packed));
static inline void *
read_pointer (void *p)
{ union unaligned *up = p; return up->p; }
static inline unsigned
read_1byte (void *p)
{ return *(unsigned char *)p; }
static inline unsigned
read_2byte (void *p)
{ union unaligned *up = p; return up->b2; }
static inline unsigned
read_4byte (void *p)
{ union unaligned *up = p; return up->b4; }
static inline unsigned long
read_8byte (void *p)
{ union unaligned *up = p; return up->b8; }
/* Ordering function for FDEs. Functions can't overlap, so we just compare
their starting addresses. */
static inline saddr
fde_compare (fde *x, fde *y)
{
return (saddr)x->pc_begin - (saddr)y->pc_begin;
}
/* Return the address of the FDE after P. */
static inline fde *
next_fde (fde *p)
{
return (fde *)(((char *)p) + p->length + sizeof (p->length));
}
#include "frame.c"
static size_t
count_fdes (fde *this_fde)
{
size_t count;
for (count = 0; this_fde->length != 0; this_fde = next_fde (this_fde))
{
/* Skip CIEs and linked once FDE entries. */
if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
continue;
++count;
}
return count;
}
static void
add_fdes (fde *this_fde, fde_accumulator *accu, void **beg_ptr, void **end_ptr)
{
void *pc_begin = *beg_ptr;
void *pc_end = *end_ptr;
for (; this_fde->length != 0; this_fde = next_fde (this_fde))
{
/* Skip CIEs and linked once FDE entries. */
if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
continue;
fde_insert (accu, this_fde);
if (this_fde->pc_begin < pc_begin)
pc_begin = this_fde->pc_begin;
if (this_fde->pc_begin + this_fde->pc_range > pc_end)
pc_end = this_fde->pc_begin + this_fde->pc_range;
}
*beg_ptr = pc_begin;
*end_ptr = pc_end;
}
/* search this fde table for the one containing the pc */
static fde *
search_fdes (fde *this_fde, void *pc)
{
for (; this_fde->length != 0; this_fde = next_fde (this_fde))
{
/* Skip CIEs and linked once FDE entries. */
if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
continue;
if ((uaddr)((char *)pc - (char *)this_fde->pc_begin) < this_fde->pc_range)
return this_fde;
}
return NULL;
}
/* Set up a sorted array of pointers to FDEs for a loaded object. We
count up the entries before allocating the array because it's likely to
be faster. We can be called multiple times, should we have failed to
allocate a sorted fde array on a previous occasion. */
static void
frame_init (struct object* ob)
{
size_t count;
fde_accumulator accu;
void *pc_begin, *pc_end;
fde **array;
if (ob->pc_begin)
count = ob->count;
else if (ob->fde_array)
{
fde **p = ob->fde_array;
for (count = 0; *p; ++p)
count += count_fdes (*p);
}
else
count = count_fdes (ob->fde_begin);
ob->count = count;
if (!start_fde_sort (&accu, count) && ob->pc_begin)
return;
pc_begin = (void*)(uaddr)-1;
pc_end = 0;
if (ob->fde_array)
{
fde **p = ob->fde_array;
for (; *p; ++p)
add_fdes (*p, &accu, &pc_begin, &pc_end);
}
else
add_fdes (ob->fde_begin, &accu, &pc_begin, &pc_end);
array = end_fde_sort (&accu, count);
if (array)
ob->fde_array = array;
ob->pc_begin = pc_begin;
ob->pc_end = pc_end;
}
/* Return a pointer to the FDE for the function containing PC. */
static fde *
find_fde (void *pc)
{
struct object *ob;
size_t lo, hi;
init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
/* Linear search through the objects, to find the one containing the pc. */
for (ob = objects; ob; ob = ob->next)
{
if (ob->pc_begin == 0)
frame_init (ob);
if (pc >= ob->pc_begin && pc < ob->pc_end)
break;
}
if (ob == 0)
{
__gthread_mutex_unlock (&object_mutex);
return 0;
}
if (!ob->fde_array || (void *)ob->fde_array == (void *)ob->fde_begin)
frame_init (ob);
if (ob->fde_array && (void *)ob->fde_array != (void *)ob->fde_begin)
{
__gthread_mutex_unlock (&object_mutex);
/* Standard binary search algorithm. */
for (lo = 0, hi = ob->count; lo < hi; )
{
size_t i = (lo + hi) / 2;
fde *f = ob->fde_array[i];
if (pc < f->pc_begin)
hi = i;
else if (pc >= f->pc_begin + f->pc_range)
lo = i + 1;
else
return f;
}
}
else
{
/* Long slow labourious linear search, cos we've no memory. */
fde *f;
if (ob->fde_array)
{
fde **p = ob->fde_array;
do
{
f = search_fdes (*p, pc);
if (f)
break;
p++;
}
while (*p);
}
else
f = search_fdes (ob->fde_begin, pc);
__gthread_mutex_unlock (&object_mutex);
return f;
}
return 0;
}
static inline struct dwarf_cie *
get_cie (fde *f)
{
return ((void *)&f->CIE_delta) - f->CIE_delta;
}
/* Extract any interesting information from the CIE for the translation
unit F belongs to. */
static void *
extract_cie_info (fde *f, struct cie_info *c)
{
void *p;
int i;
c->augmentation = get_cie (f)->augmentation;
if (strcmp (c->augmentation, "") != 0
&& strcmp (c->augmentation, "eh") != 0
&& c->augmentation[0] != 'z')
return 0;
p = c->augmentation + strlen (c->augmentation) + 1;
if (strcmp (c->augmentation, "eh") == 0)
{
c->eh_ptr = read_pointer (p);
p += sizeof (void *);
}
else
c->eh_ptr = 0;
p = decode_uleb128 (p, &c->code_align);
p = decode_sleb128 (p, &c->data_align);
c->ra_regno = *(unsigned char *)p++;
/* If the augmentation starts with 'z', we now see the length of the
augmentation fields. */
if (c->augmentation[0] == 'z')
{
p = decode_uleb128 (p, &i);
p += i;
}
return p;
}
/* Decode a DW_OP stack operation. */
static void *
decode_stack_op (unsigned char *buf, struct frame_state *state)
{
enum dwarf_location_atom op;
int offset;
op = *buf++;
switch (op)
{
case DW_OP_reg0:
case DW_OP_reg1:
case DW_OP_reg2:
case DW_OP_reg3:
case DW_OP_reg4:
case DW_OP_reg5:
case DW_OP_reg6:
case DW_OP_reg7:
case DW_OP_reg8:
case DW_OP_reg9:
case DW_OP_reg10:
case DW_OP_reg11:
case DW_OP_reg12:
case DW_OP_reg13:
case DW_OP_reg14:
case DW_OP_reg15:
case DW_OP_reg16:
case DW_OP_reg17:
case DW_OP_reg18:
case DW_OP_reg19:
case DW_OP_reg20:
case DW_OP_reg21:
case DW_OP_reg22:
case DW_OP_reg23:
case DW_OP_reg24:
case DW_OP_reg25:
case DW_OP_reg26:
case DW_OP_reg27:
case DW_OP_reg28:
case DW_OP_reg29:
case DW_OP_reg30:
case DW_OP_reg31:
state->cfa_reg = op - DW_OP_reg0;
break;
case DW_OP_regx:
buf = decode_sleb128 (buf, &offset);
state->cfa_reg = offset;
break;
case DW_OP_breg0:
case DW_OP_breg1:
case DW_OP_breg2:
case DW_OP_breg3:
case DW_OP_breg4:
case DW_OP_breg5:
case DW_OP_breg6:
case DW_OP_breg7:
case DW_OP_breg8:
case DW_OP_breg9:
case DW_OP_breg10:
case DW_OP_breg11:
case DW_OP_breg12:
case DW_OP_breg13:
case DW_OP_breg14:
case DW_OP_breg15:
case DW_OP_breg16:
case DW_OP_breg17:
case DW_OP_breg18:
case DW_OP_breg19:
case DW_OP_breg20:
case DW_OP_breg21:
case DW_OP_breg22:
case DW_OP_breg23:
case DW_OP_breg24:
case DW_OP_breg25:
case DW_OP_breg26:
case DW_OP_breg27:
case DW_OP_breg28:
case DW_OP_breg29:
case DW_OP_breg30:
case DW_OP_breg31:
state->cfa_reg = op - DW_OP_breg0;
buf = decode_sleb128 (buf, &offset);
state->base_offset = offset;
break;
case DW_OP_bregx:
buf = decode_sleb128 (buf, &offset);
state->cfa_reg = offset;
buf = decode_sleb128 (buf, &offset);
state->base_offset = offset;
break;
case DW_OP_deref:
state->indirect = 1;
break;
case DW_OP_plus_uconst:
buf = decode_uleb128 (buf, &offset);
state->cfa_offset = offset;
break;
default:
abort ();
}
return buf;
}
/* Decode one instruction's worth of DWARF 2 call frame information.
Used by __frame_state_for. Takes pointers P to the instruction to
decode, STATE to the current register unwind information, INFO to the
current CIE information, and PC to the current PC value. Returns a
pointer to the next instruction. */
static void *
execute_cfa_insn (void *p, struct frame_state_internal *state,
struct cie_info *info, void **pc)
{
unsigned insn = *(unsigned char *)p++;
unsigned reg;
int offset;
if (insn & DW_CFA_advance_loc)
*pc += ((insn & 0x3f) * info->code_align);
else if (insn & DW_CFA_offset)
{
reg = (insn & 0x3f);
p = decode_uleb128 (p, &offset);
if (reg == state->s.cfa_reg)
/* Don't record anything about this register; it's only used to
reload SP in the epilogue. We don't want to copy in SP
values for outer frames; we handle restoring SP specially. */;
else
{
offset *= info->data_align;
state->s.saved[reg] = REG_SAVED_OFFSET;
state->s.reg_or_offset[reg] = offset;
}
}
else if (insn & DW_CFA_restore)
{
reg = (insn & 0x3f);
state->s.saved[reg] = REG_UNSAVED;
}
else switch (insn)
{
case DW_CFA_set_loc:
*pc = read_pointer (p);
p += sizeof (void *);
break;
case DW_CFA_advance_loc1:
*pc += read_1byte (p);
p += 1;
break;
case DW_CFA_advance_loc2:
*pc += read_2byte (p);
p += 2;
break;
case DW_CFA_advance_loc4:
*pc += read_4byte (p);
p += 4;
break;
case DW_CFA_offset_extended:
p = decode_uleb128 (p, &reg);
p = decode_uleb128 (p, &offset);
if (reg == state->s.cfa_reg)
/* Don't record anything; see above. */;
else
{
offset *= info->data_align;
state->s.saved[reg] = REG_SAVED_OFFSET;
state->s.reg_or_offset[reg] = offset;
}
break;
case DW_CFA_restore_extended:
p = decode_uleb128 (p, &reg);
state->s.saved[reg] = REG_UNSAVED;
break;
case DW_CFA_undefined:
case DW_CFA_same_value:
case DW_CFA_nop:
break;
case DW_CFA_register:
{
unsigned reg2;
p = decode_uleb128 (p, &reg);
p = decode_uleb128 (p, &reg2);
state->s.saved[reg] = REG_SAVED_REG;
state->s.reg_or_offset[reg] = reg2;
}
break;
case DW_CFA_def_cfa:
p = decode_uleb128 (p, &reg);
p = decode_uleb128 (p, &offset);
state->s.cfa_reg = reg;
state->s.cfa_offset = offset;
break;
case DW_CFA_def_cfa_register:
p = decode_uleb128 (p, &reg);
state->s.cfa_reg = reg;
break;
case DW_CFA_def_cfa_offset:
p = decode_uleb128 (p, &offset);
state->s.cfa_offset = offset;
break;
case DW_CFA_def_cfa_expression:
{
void *end;
state->s.cfa_reg = 0;
state->s.cfa_offset = 0;
state->s.base_offset = 0;
state->s.indirect = 0;
p = decode_uleb128 (p, &offset);
end = p + offset;
while (p < end)
p = decode_stack_op (p, &(state->s));
break;
}
case DW_CFA_remember_state:
{
struct frame_state_internal *save =
(struct frame_state_internal *)
malloc (sizeof (struct frame_state_internal));
memcpy (save, state, sizeof (struct frame_state_internal));
state->saved_state = save;
}
break;
case DW_CFA_restore_state:
{
struct frame_state_internal *save = state->saved_state;
memcpy (state, save, sizeof (struct frame_state_internal));
free (save);
}
break;
/* FIXME: Hardcoded for SPARC register window configuration. */
case DW_CFA_GNU_window_save:
for (reg = 16; reg < 32; ++reg)
{
state->s.saved[reg] = REG_SAVED_OFFSET;
state->s.reg_or_offset[reg] = (reg - 16) * sizeof (void *);
}
break;
case DW_CFA_GNU_args_size:
p = decode_uleb128 (p, &offset);
state->s.args_size = offset;
break;
case DW_CFA_GNU_negative_offset_extended:
p = decode_uleb128 (p, &reg);
p = decode_uleb128 (p, &offset);
offset *= info->data_align;
state->s.saved[reg] = REG_SAVED_OFFSET;
state->s.reg_or_offset[reg] = -offset;
break;
default:
abort ();
}
return p;
}
/* Called from __throw to find the registers to restore for a given
PC_TARGET. The caller should allocate a local variable of `struct
frame_state' (declared in frame.h) and pass its address to STATE_IN. */
struct frame_state *
__frame_state_for (void *pc_target, struct frame_state *state_in)
{
fde *f;
void *insn, *end, *pc;
struct cie_info info;
struct frame_state_internal state;
f = find_fde (pc_target);
if (f == 0)
return 0;
insn = extract_cie_info (f, &info);
if (insn == 0)
return 0;
memset (&state, 0, sizeof (state));
state.s.retaddr_column = info.ra_regno;
state.s.eh_ptr = info.eh_ptr;
/* First decode all the insns in the CIE. */
end = next_fde ((fde*) get_cie (f));
while (insn < end)
insn = execute_cfa_insn (insn, &state, &info, 0);
insn = ((fde *)f) + 1;
if (info.augmentation[0] == 'z')
{
int i;
insn = decode_uleb128 (insn, &i);
insn += i;
}
/* Then the insns in the FDE up to our target PC. */
end = next_fde (f);
pc = f->pc_begin;
while (insn < end && pc <= pc_target)
insn = execute_cfa_insn (insn, &state, &info, &pc);
memcpy (state_in, &state.s, sizeof (state.s));
return state_in;
}
#endif /* DWARF2_UNWIND_INFO */

View File

@ -1,287 +0,0 @@
/* Header file for unwinding stack frames for exception handling. */
/* Compile this one with gcc. */
/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@cygnus.com>.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef DWARF_FRAME_REGISTERS
#define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
#endif
typedef struct frame_state
{
void *cfa;
void *eh_ptr;
long cfa_offset;
long args_size;
long reg_or_offset[DWARF_FRAME_REGISTERS+1];
unsigned short cfa_reg;
unsigned short retaddr_column;
char saved[DWARF_FRAME_REGISTERS+1];
long base_offset;
char indirect;
} frame_state;
/* Values for 'saved' above. */
#define REG_UNSAVED 0
#define REG_SAVED_OFFSET 1
#define REG_SAVED_REG 2
/* The representation for an "object" to be searched for frame unwind info.
For targets with named sections, one object is an executable or shared
library; for other targets, one object is one translation unit.
A copy of this structure declaration is printed by collect2.c;
keep the copies synchronized! */
struct object {
#ifdef IA64_UNWIND_INFO
void *pc_base; /* This field will be set by find_fde. */
#endif
void *pc_begin;
void *pc_end;
struct dwarf_fde *fde_begin;
#ifdef IA64_UNWIND_INFO
struct dwarf_fde *fde_end;
#endif
struct dwarf_fde **fde_array;
size_t count;
struct object *next;
};
/* Note the following routines are exported interfaces from libgcc; do not
change these interfaces. Instead create new interfaces. Also note
references to these functions may be made weak in files where they
are referenced. */
extern void __register_frame (void * );
extern void __register_frame_table (void *);
extern void __deregister_frame (void *);
/* Called either from crtbegin.o or a static constructor to register the
unwind info for an object or translation unit, respectively. */
extern void __register_frame_info (void *, struct object *);
/* Similar, but BEGIN is actually a pointer to a table of unwind entries
for different translation units. Called from the file generated by
collect2. */
extern void __register_frame_info_table (void *, struct object *);
/* Called from crtend.o to deregister the unwind info for an object. */
extern void *__deregister_frame_info (void *);
/* Called from __throw to find the registers to restore for a given
PC_TARGET. The caller should allocate a local variable of `struct
frame_state' (declared in frame.h) and pass its address to STATE_IN.
Returns NULL on failure, otherwise returns STATE_IN. */
extern struct frame_state *__frame_state_for (void *, struct frame_state *);
#ifdef IA64_UNWIND_INFO
/* This is the information required for unwind records in an ia64
object file. This is required by GAS and the compiler runtime. */
/* These are the starting point masks for the various types of
unwind records. To create a record of type R3 for instance, one
starts by using the value UNW_R3 and or-ing in any other required values.
These values are also unique (in context), so they can be used to identify
the various record types as well. UNW_Bx and some UNW_Px do have the
same value, but Px can only occur in a prologue context, and Bx in
a body context. */
#define UNW_R1 0x00
#define UNW_R2 0x40
#define UNW_R3 0x60
#define UNW_P1 0x80
#define UNW_P2 0xA0
#define UNW_P3 0xB0
#define UNW_P4 0xB8
#define UNW_P5 0xB9
#define UNW_P6 0xC0
#define UNW_P7 0xE0
#define UNW_P8 0xF0
#define UNW_P9 0xF1
#define UNW_P10 0xFF
#define UNW_X1 0xF9
#define UNW_X2 0xFA
#define UNW_X3 0xFB
#define UNW_X4 0xFC
#define UNW_B1 0x80
#define UNW_B2 0xC0
#define UNW_B3 0xE0
#define UNW_B4 0xF0
/* These are all the various types of unwind records. */
typedef enum
{
prologue, prologue_gr, body, mem_stack_f, mem_stack_v, psp_gr, psp_sprel,
rp_when, rp_gr, rp_br, rp_psprel, rp_sprel, pfs_when, pfs_gr, pfs_psprel,
pfs_sprel, preds_when, preds_gr, preds_psprel, preds_sprel,
fr_mem, frgr_mem, gr_gr, gr_mem, br_mem, br_gr, spill_base, spill_mask,
unat_when, unat_gr, unat_psprel, unat_sprel, lc_when, lc_gr, lc_psprel,
lc_sprel, fpsr_when, fpsr_gr, fpsr_psprel, fpsr_sprel,
priunat_when_gr, priunat_when_mem, priunat_gr, priunat_psprel,
priunat_sprel, bsp_when, bsp_gr, bsp_psprel, bsp_sprel, bspstore_when,
bspstore_gr, bspstore_psprel, bspstore_sprel, rnat_when, rnat_gr,
rnat_psprel, rnat_sprel, epilogue, label_state, copy_state,
spill_psprel, spill_sprel, spill_reg, spill_psprel_p, spill_sprel_p,
spill_reg_p
} unw_record_type;
/* These structures declare the fields that can be used in each of the
4 record formats, R, P, B and X. */
typedef struct unw_r_record
{
unsigned long rlen;
unsigned short mask;
unsigned short grsave;
} unw_r_record;
typedef struct unw_p_record
{
void *imask;
unsigned long t;
unsigned long size;
unsigned long spoff;
unsigned long br;
unsigned long pspoff;
unsigned short gr;
unsigned short rmask;
unsigned short grmask;
unsigned long frmask;
unsigned short brmask;
} unw_p_record;
typedef struct unw_b_record
{
unsigned long t;
unsigned long label;
unsigned short ecount;
} unw_b_record;
typedef struct unw_x_record
{
unsigned long t;
unsigned long spoff;
unsigned long pspoff;
unsigned short reg;
unsigned short treg;
unsigned short qp;
unsigned short xy; /* Value of the XY field.. */
} unw_x_record;
/* This structure is used to determine the specific record type and
its fields. */
typedef struct unwind_record
{
unw_record_type type;
union {
unw_r_record r;
unw_p_record p;
unw_b_record b;
unw_x_record x;
} record;
} unwind_record;
#define IA64_UNW_LOC_TYPE_NONE 0
#define IA64_UNW_LOC_TYPE_MEM 1
#define IA64_UNW_LOC_TYPE_GR 2
#define IA64_UNW_LOC_TYPE_FR 3
#define IA64_UNW_LOC_TYPE_BR 4
#define IA64_UNW_LOC_TYPE_SPOFF 5
#define IA64_UNW_LOC_TYPE_PSPOFF 6
#define IA64_UNW_LOC_TYPE_OFFSET 7
#define IA64_UNW_LOC_TYPE_SPILLBASE 8
typedef struct ia64_reg_loc
{
long when; /* PC relative offset from start of function. */
union { /* In memory or another register? */
void *mem;
int regno;
int offset;
} l;
short loc_type; /* Where to find value. */
short reg_size;
} ia64_reg_loc;
/* Frame information record. */
typedef struct ia64_frame_state
{
ia64_reg_loc gr[4]; /* gr4 to gr7. */
ia64_reg_loc fr[20]; /* fr2 to fr5, fr16 to fr31. */
ia64_reg_loc br[5]; /* br1 to br5. */
ia64_reg_loc rp;
ia64_reg_loc fpsr;
ia64_reg_loc bsp;
ia64_reg_loc bspstore;
ia64_reg_loc rnat;
ia64_reg_loc pfs;
ia64_reg_loc unat;
ia64_reg_loc lc;
ia64_reg_loc pr;
ia64_reg_loc priunat;
ia64_reg_loc sp;
ia64_reg_loc psp;
ia64_reg_loc spill_base;
void *my_psp;
void *my_sp;
void *my_bsp;
} ia64_frame_state;
/* This structure represents the start of an unwind information pointer.
'unwind_descriptors' is the beginninng of the unwind descriptors, which
use up 'length' bytes of storage. */
typedef struct unwind_info_ptr
{
unsigned long header; /* version, flags, & length */
unsigned char unwind_descriptors[1];
} unwind_info_ptr;
#define IA64_UNW_HDR_LENGTH(x) ((x) & 0x00000000ffffffffUL)
#define IA64_UNW_HDR_FLAGS(x) (((x) >> 32) & 0xffffUL)
#define IA64_UNW_HDR_VERSION(x) (((x) >> 48) & 0xffffUL)
/* Header flag bits, after extraction by IA64_UNW_HDR_FLAGS. */
#define IA64_UNW_EHANDLER 0x1
#define IA64_UNW_UHANDLER 0x2
extern void * __ia64_personality_v1 (void *pc, old_exception_table *table);
extern unwind_info_ptr *__build_ia64_frame_state (unsigned char *,
ia64_frame_state *,
void *, void *,
void **);
extern void *__get_real_reg_value (ia64_reg_loc *);
extern void *__get_personality (unwind_info_ptr *);
extern void *__get_except_table (unwind_info_ptr *);
extern void __set_real_reg_value (ia64_reg_loc *, void *);
void *__calc_caller_bsp (long, unsigned char *);
void __copy_saved_reg_state (ia64_frame_state *, ia64_frame_state *);
#endif /* IA64_UNWIND_INFO */

View File

@ -1580,11 +1580,6 @@ fixup_var_refs (var, promoted_mode, unsignedp, ht)
end_sequence ();
}
}
/* Scan the catch clauses for exception handling too. */
push_to_full_sequence (catch_clauses, catch_clauses_last);
fixup_var_refs_insns (catch_clauses, var, promoted_mode, unsignedp, 0);
end_full_sequence (&catch_clauses, &catch_clauses_last);
}
/* REPLACEMENTS is a pointer to a list of the struct fixup_replacement and X is
@ -6315,20 +6310,10 @@ expand_function_start (subr, parms_have_cleanups)
else
cleanup_label = 0;
/* Make the label for return statements to jump to, if this machine
does not have a one-instruction return and uses an epilogue,
or if it returns a structure, or if it has parm cleanups. */
#ifdef HAVE_return
if (cleanup_label == 0 && HAVE_return
&& ! current_function_instrument_entry_exit
&& ! current_function_returns_pcc_struct
&& ! (current_function_returns_struct && ! optimize))
return_label = 0;
else
return_label = gen_label_rtx ();
#else
/* Make the label for return statements to jump to. Do not special
case machines with special return instructions -- they will be
handled later during jump, ifcvt, or epilogue creation. */
return_label = gen_label_rtx ();
#endif
/* Initialize rtx used to return the value. */
/* Do this before assign_parms so that we copy the struct value address
@ -6370,7 +6355,9 @@ expand_function_start (subr, parms_have_cleanups)
else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode)
/* If return mode is void, this decl rtl should not be used. */
SET_DECL_RTL (DECL_RESULT (subr), NULL_RTX);
else if (parms_have_cleanups || current_function_instrument_entry_exit)
else if (parms_have_cleanups
|| current_function_instrument_entry_exit
|| (flag_exceptions && USING_SJLJ_EXCEPTIONS))
{
/* If function will end with cleanup code for parms,
compute the return values into a pseudo reg,
@ -6801,27 +6788,6 @@ expand_function_end (filename, line, end_bindings)
if (end_bindings)
expand_end_bindings (0, 0, 0);
/* Now handle any leftover exception regions that may have been
created for the parameters. */
{
rtx last = get_last_insn ();
rtx label;
expand_leftover_cleanups ();
/* If there are any catch_clauses remaining, output them now. */
emit_insns (catch_clauses);
catch_clauses = catch_clauses_last = NULL_RTX;
/* If the above emitted any code, may sure we jump around it. */
if (last != get_last_insn ())
{
label = gen_label_rtx ();
last = emit_jump_insn_after (gen_jump (label), last);
last = emit_barrier_after (last);
emit_label (label);
}
}
if (current_function_instrument_entry_exit)
{
rtx fun = DECL_RTL (current_function_decl);
@ -6837,6 +6803,11 @@ expand_function_end (filename, line, end_bindings)
Pmode);
}
/* Let except.c know where it should emit the call to unregister
the function context for sjlj exceptions. */
if (flag_exceptions && USING_SJLJ_EXCEPTIONS)
sjlj_emit_function_exit_after (get_last_insn ());
/* If we had calls to alloca, and this machine needs
an accurate stack pointer to exit the function,
insert some code to save and restore the stack pointer. */
@ -6944,16 +6915,16 @@ expand_function_end (filename, line, end_bindings)
current_function_return_rtx = outgoing;
}
/* If this is an implementation of throw, do what's necessary to
communicate between __builtin_eh_return and the epilogue. */
expand_eh_return ();
/* ??? This should no longer be necessary since stupid is no longer with
us, but there are some parts of the compiler (eg reload_combine, and
sh mach_dep_reorg) that still try and compute their own lifetime info
instead of using the general framework. */
use_return_register ();
/* If this is an implementation of __throw, do what's necessary to
communicate between __builtin_eh_return and the epilogue. */
expand_eh_return ();
/* Output a return insn if we are using one.
Otherwise, let the rtl chain end here, to drop through
into the epilogue. */

View File

@ -409,6 +409,9 @@ struct function
either as a subroutine or builtin. */
unsigned int calls_alloca : 1;
/* Nonzero if the function calls __builtin_eh_return. */
unsigned int calls_eh_return : 1;
/* Nonzero if function being compiled receives nonlocal gotos
from nested functions. */
unsigned int has_nonlocal_label : 1;
@ -488,6 +491,7 @@ extern struct function *all_functions;
#define current_function_calls_setjmp (cfun->calls_setjmp)
#define current_function_calls_alloca (cfun->calls_alloca)
#define current_function_calls_longjmp (cfun->calls_longjmp)
#define current_function_calls_eh_return (cfun->calls_eh_return)
#define current_function_has_computed_jump (cfun->has_computed_jump)
#define current_function_contains_functions (cfun->contains_functions)
#define current_function_is_thunk (cfun->is_thunk)

View File

@ -1905,7 +1905,7 @@ find_if_block (test_bb, then_edge, else_edge)
/* Make sure IF, THEN, and ELSE, blocks are adjacent. Actually, we
get the first condition for free, since we've already asserted that
there's a fallthru edge from IF to THEN. */
/* ??? As an enhancement, move the ELSE block. Have to deal with EH and
/* ??? As an enhancement, move the ELSE block. Have to deal with
BLOCK notes, if by no other means than aborting the merge if they
exist. Sticky enough I don't want to think about it now. */
next_index = then_bb->index;
@ -2188,15 +2188,6 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
{
rtx head, end, jump, earliest, old_dest;
/* No code movement can occur if we'd be scrogging EH regions.
Within MERGE_BB, ensure that we've not got stray EH_BEG or EH_END
notes within the block. Between the blocks, checking that the end
region numbers match ensures that we won't disrupt the nesting
between regions. */
if (merge_bb->eh_beg != merge_bb->eh_end
|| merge_bb->eh_end != test_bb->eh_end)
return FALSE;
jump = test_bb->end;
/* Find the extent of the real code in the merge block. */

View File

@ -81,12 +81,12 @@ static void set_block_abstract_flags PARAMS ((tree, int));
static void process_reg_param PARAMS ((struct inline_remap *, rtx,
rtx));
void set_decl_abstract_flags PARAMS ((tree, int));
static rtx expand_inline_function_eh_labelmap PARAMS ((rtx));
static void mark_stores PARAMS ((rtx, rtx, void *));
static void save_parm_insns PARAMS ((rtx, rtx));
static void copy_insn_list PARAMS ((rtx, struct inline_remap *,
rtx));
static void copy_insn_notes PARAMS ((rtx, struct inline_remap *));
static void copy_insn_notes PARAMS ((rtx, struct inline_remap *,
int));
static int compare_blocks PARAMS ((const PTR, const PTR));
static int find_block PARAMS ((const PTR, const PTR));
@ -152,6 +152,9 @@ function_cannot_inline_p (fndecl)
if (current_function_calls_setjmp)
return N_("function using setjmp cannot be inline");
if (current_function_calls_eh_return)
return N_("function uses __builtin_eh_return");
if (current_function_contains_functions)
return N_("function with nested functions cannot be inline");
@ -221,19 +224,6 @@ function_cannot_inline_p (fndecl)
if (current_function_has_nonlocal_goto)
return N_("function with nonlocal goto cannot be inline");
/* This is a hack, until the inliner is taught about eh regions at
the start of the function. */
for (insn = get_insns ();
insn
&& ! (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG);
insn = NEXT_INSN (insn))
{
if (insn && GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
return N_("function with complex parameters cannot be inline");
}
/* We can't inline functions that return a PARALLEL rtx. */
if (DECL_RTL_SET_P (DECL_RESULT (fndecl)))
{
@ -548,17 +538,6 @@ process_reg_param (map, loc, copy)
map->reg_map[REGNO (loc)] = copy;
}
/* Used by duplicate_eh_handlers to map labels for the exception table */
static struct inline_remap *eif_eh_map;
static rtx
expand_inline_function_eh_labelmap (label)
rtx label;
{
int index = CODE_LABEL_NUMBER (label);
return get_label_from_map (eif_eh_map, index);
}
/* Compare two BLOCKs for qsort. The key we sort on is the
BLOCK_ABSTRACT_ORIGIN of the blocks. */
@ -634,6 +613,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
rtvec arg_vector = (rtvec) inl_f->original_arg_vector;
rtx static_chain_value = 0;
int inl_max_uid;
int eh_region_offset;
/* The pointer used to track the true location of the memory used
for MAP->LABEL_MAP. */
@ -1140,8 +1120,14 @@ expand_inline_function (fndecl, parms, target, ignore, type,
/* Now copy the insns one by one. */
copy_insn_list (insns, map, static_chain_value);
/* Duplicate the EH regions. This will create an offset from the
region numbers in the function we're inlining to the region
numbers in the calling function. This must wait until after
copy_insn_list, as we need the insn map to be complete. */
eh_region_offset = duplicate_eh_regions (inl_f, map);
/* Now copy the REG_NOTES for those insns. */
copy_insn_notes (insns, map);
copy_insn_notes (insns, map, eh_region_offset);
/* If the insn sequence required one, emit the return label. */
if (map->local_return_label)
@ -1260,12 +1246,6 @@ copy_insn_list (insns, map, static_chain_value)
inline_target. */
break;
/* If the inline fn needs eh context, make sure that
the current fn has one. */
if (GET_CODE (pattern) == USE
&& find_reg_note (insn, REG_EH_CONTEXT, 0) != 0)
get_eh_context ();
/* Ignore setting a function value that we don't want to use. */
if (map->inline_target == 0
&& set != 0
@ -1526,31 +1506,9 @@ copy_insn_list (insns, map, static_chain_value)
copy = emit_note (NOTE_SOURCE_FILE (insn),
NOTE_LINE_NUMBER (insn));
if (copy
&& (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG
|| NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_END))
{
rtx label
= get_label_from_map (map, NOTE_EH_HANDLER (copy));
/* We have to duplicate the handlers for the original. */
if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG)
{
/* We need to duplicate the handlers for the EH region
and we need to indicate where the label map is */
eif_eh_map = map;
duplicate_eh_handlers (NOTE_EH_HANDLER (copy),
CODE_LABEL_NUMBER (label),
expand_inline_function_eh_labelmap);
}
/* We have to forward these both to match the new exception
region. */
NOTE_EH_HANDLER (copy) = CODE_LABEL_NUMBER (label);
}
else if (copy
&& (NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_BEG
|| NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_END)
&& NOTE_BLOCK (insn))
&& (NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_BEG
|| NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_END)
&& NOTE_BLOCK (insn))
{
tree *mapped_block_p;
@ -1587,9 +1545,10 @@ copy_insn_list (insns, map, static_chain_value)
that are valid across the entire function. */
static void
copy_insn_notes (insns, map)
copy_insn_notes (insns, map, eh_region_offset)
rtx insns;
struct inline_remap *map;
int eh_region_offset;
{
rtx insn, new_insn;
@ -1620,6 +1579,9 @@ copy_insn_notes (insns, map)
next = XEXP (note, 1);
if (REG_NOTE_KIND (note) == REG_LABEL)
remove_note (new_insn, note);
else if (REG_NOTE_KIND (note) == REG_EH_REGION)
XEXP (note, 0) = GEN_INT (INTVAL (XEXP (note, 0))
+ eh_region_offset);
}
}
@ -1628,8 +1590,12 @@ copy_insn_notes (insns, map)
{
int i;
for (i = 0; i < 3; i++)
copy_insn_notes (XEXP (PATTERN (insn), i), map);
copy_insn_notes (XEXP (PATTERN (insn), i), map, eh_region_offset);
}
if (GET_CODE (insn) == JUMP_INSN
&& GET_CODE (PATTERN (insn)) == RESX)
XINT (PATTERN (new_insn), 0) += eh_region_offset;
}
}
@ -2071,12 +2037,6 @@ copy_rtx_and_substitute (orig, map, for_lhs)
copy_rtx_and_substitute (constant, map, for_lhs)),
0);
}
else if (SYMBOL_REF_NEED_ADJUST (orig))
{
eif_eh_map = map;
return rethrow_symbol_map (orig,
expand_inline_function_eh_labelmap);
}
return orig;

View File

@ -1,3 +1,34 @@
2001-03-28 Richard Henderson <rth@redhat.com>
IA-64 ABI Exception Handling:
* Make-lang.in (except.o): Don't depend on eh-common.h.
* check-init.c (check_init): Handle EXC_PTR_EXPR.
* decl.c (init_decl_processing) [throw_node]: No _Jv_Sjlj_Throw.
[soft_exceptioninfo_call_node]: Remove.
[eh_personality_libfunc, lang_eh_runtime_type]: New.
(end_java_method): No emit_handlers.
* except.c (java_set_exception_lang_code): Remove.
(method_init_exceptions): Don't call it.
(prepare_eh_table_type): No CATCH_ALL_TYPE.
(build_exception_object_ref): New.
(expand_end_java_handler): Update for except.h name changes.
(emit_handlers, expand_resume_after_catch): Remove.
* expr.c (java_lang_expand_expr): Update for except.h name changes.
(process_jvm_instruction): Use build_exception_object_ref.
* java-tree.h (JTI_SOFT_EXCEPTIONINFO_CALL_NODE): Remove.
(soft_exceptioninfo_call_node): Remove.
(build_exception_object_ref): Declare.
* jcf-write.c (generate_bytecode_insns) [CALL_EXPR]: No
soft_exceptioninfo_call_node. Move processing ...
[EXC_PTR_EXPR]: ... here.
* parse.h (BUILD_ASSIGN_EXCEPTION_INFO): Remove dead code.
* parse.y (catch_clause_parameter): Use build_exception_object_ref.
(source_end_java_method): No java_set_exception_lang_code or
emit_handlers.
(build_dot_class_method): Use build_exception_object_ref.
(try_reference_assignconv): Check EXC_PTR_EXPR not
soft_exceptioninfo_call_node.
2001-03-28 Richard Henderson <rth@redhat.com>
* java-tree.h (throw_node): Define as a single member of

View File

@ -254,7 +254,7 @@ java/decl.o: java/decl.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h \
toplev.h $(SYSTEM_H) function.h gcc.h
java/except.o: java/except.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h real.h \
$(RTL_H) java/javaop.h java/java-opcodes.h except.h java/java-except.h \
eh-common.h toplev.h $(SYSTEM_H) function.h
toplev.h $(SYSTEM_H) function.h
java/expr.o: java/expr.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h real.h \
$(RTL_H) $(EXPR_H) java/javaop.h java/java-opcodes.h except.h \
java/java-except.h java/java-except.h java/parse.h toplev.h \

View File

@ -681,6 +681,7 @@ check_init (exp, before)
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
case EXC_PTR_EXPR:
break;
case NEW_CLASS_EXPR:

View File

@ -29,12 +29,14 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "config.h"
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "toplev.h"
#include "flags.h"
#include "java-tree.h"
#include "jcf.h"
#include "toplev.h"
#include "function.h"
#include "expr.h"
#include "except.h"
#include "java-except.h"
#include "ggc.h"
@ -725,13 +727,14 @@ init_decl_processing ()
t),
0, NOT_BUILT_IN,
NULL_PTR);
throw_node = builtin_function ((USING_SJLJ_EXCEPTIONS
? "_Jv_Throw" : "_Jv_Sjlj_Throw"),
throw_node = builtin_function ("_Jv_Throw",
build_function_type (ptr_type_node, t),
0, NOT_BUILT_IN, NULL_PTR);
/* Mark throw_nodes as `noreturn' functions with side effects. */
TREE_THIS_VOLATILE (throw_node) = 1;
TREE_SIDE_EFFECTS (throw_node) = 1;
t = build_function_type (int_type_node, endlink);
soft_monitorenter_node
= builtin_function ("_Jv_MonitorEnter", t, 0, NOT_BUILT_IN,
@ -834,15 +837,6 @@ init_decl_processing ()
build_function_type (double_type_node, t),
BUILT_IN_FMOD, BUILT_IN_NORMAL, "fmod");
soft_exceptioninfo_call_node
= build (CALL_EXPR,
ptr_type_node,
build_address_of
(builtin_function ("_Jv_exception_info",
build_function_type (ptr_type_node, endlink),
0, NOT_BUILT_IN, NULL_PTR)),
NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (soft_exceptioninfo_call_node) = 1;
#if 0
t = tree_cons (NULL_TREE, float_type_node,
tree_cons (NULL_TREE, float_type_node, endlink));
@ -872,6 +866,12 @@ init_decl_processing ()
build_function_type (long_type_node, t),
0, NOT_BUILT_IN, NULL_PTR);
/* Initialize variables for except.c. */
eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
? "__gcj_personality_sj0"
: "__gcj_personality_v0");
lang_eh_runtime_type = prepare_eh_table_type;
init_jcf_parse ();
/* Register nodes with the garbage collector. */
@ -1828,8 +1828,6 @@ end_java_method ()
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
emit_handlers ();
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 0);

View File

@ -34,7 +34,6 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "function.h"
#include "except.h"
#include "java-except.h"
#include "eh-common.h"
#include "toplev.h"
static void expand_start_java_handler PARAMS ((struct eh_range *));
@ -250,14 +249,6 @@ method_init_exceptions ()
whole_range.first_child = NULL;
whole_range.next_sibling = NULL;
cache_range_start = 0xFFFFFF;
java_set_exception_lang_code ();
}
void
java_set_exception_lang_code ()
{
set_exception_lang_code (EH_LANG_Java);
set_exception_version_code (1);
}
/* Add an exception range. If we already have an exception range
@ -339,7 +330,7 @@ prepare_eh_table_type (type)
* (which yields a value with low-order bit 1). */
if (type == NULL_TREE)
exp = CATCH_ALL_TYPE;
exp = NULL_TREE;
else if (is_compiled_class (type))
exp = build_class_ref (type);
else
@ -350,7 +341,27 @@ prepare_eh_table_type (type)
return exp;
}
/* if there are any handlers for this range, isssue end of range,
/* Build a reference to the jthrowable object being carried in the
exception header. */
tree
build_exception_object_ref (type)
tree type;
{
tree obj;
/* Java only passes object via pointer and doesn't require adjusting.
The java object is immediately before the generic exception header. */
obj = build (EXC_PTR_EXPR, build_pointer_type (type));
obj = build (MINUS_EXPR, TREE_TYPE (obj), obj,
TYPE_SIZE_UNIT (TREE_TYPE (obj)));
obj = build1 (INDIRECT_REF, type, obj);
return obj;
}
/* If there are any handlers for this range, isssue end of range,
and then all handler blocks */
static void
expand_end_java_handler (range)
@ -361,11 +372,9 @@ expand_end_java_handler (range)
expand_start_all_catch ();
for ( ; handler != NULL_TREE; handler = TREE_CHAIN (handler))
{
start_catch_handler (prepare_eh_table_type (TREE_PURPOSE (handler)));
/* Push the thrown object on the top of the stack */
expand_start_catch (TREE_PURPOSE (handler));
expand_goto (TREE_VALUE (handler));
expand_resume_after_catch ();
end_catch_handler ();
expand_end_catch ();
}
expand_end_all_catch ();
#if defined(DEBUG_JAVA_BINDING_LEVELS)
@ -432,30 +441,3 @@ maybe_end_try (start_pc, end_pc)
current_range = current_range->outer;
}
}
/* Emit the handler labels and their code */
void
emit_handlers ()
{
if (catch_clauses)
{
rtx funcend = gen_label_rtx ();
emit_jump (funcend);
emit_insns (catch_clauses);
catch_clauses = catch_clauses_last = NULL_RTX;
expand_leftover_cleanups ();
emit_label (funcend);
}
}
/* Resume executing at the statement immediately after the end of an
exception region. */
void
expand_resume_after_catch ()
{
expand_goto (top_label_entry (&caught_return_label_stack));
}

View File

@ -2502,15 +2502,13 @@ java_lang_expand_expr (exp, target, tmode, modifier)
for (current = TREE_OPERAND (exp, 1); current;
current = TREE_CHAIN (current))
{
tree type;
tree catch = TREE_OPERAND (current, 0);
tree decl = BLOCK_EXPR_DECLS (catch);
type = (decl ? TREE_TYPE (TREE_TYPE (decl)) : NULL_TREE);
start_catch_handler (prepare_eh_table_type (type));
expand_expr_stmt (TREE_OPERAND (current, 0));
tree type = (decl ? TREE_TYPE (TREE_TYPE (decl)) : NULL_TREE);
expand_resume_after_catch ();
end_catch_handler ();
expand_start_catch (type);
expand_expr_stmt (TREE_OPERAND (current, 0));
expand_end_catch ();
}
expand_end_all_catch ();
return const0_rtx;
@ -2812,7 +2810,7 @@ process_jvm_instruction (PC, byte_ops, length)
if (instruction_bits [PC] & BCODE_EXCEPTION_TARGET)
{
tree type = pop_type (ptr_type_node);
push_value (build1 (NOP_EXPR, type, soft_exceptioninfo_call_node));
push_value (build_exception_object_ref (type));
}
switch (byte_ops[PC++])

View File

@ -339,7 +339,6 @@ enum java_tree_index
JTI_SOFT_GETJNIENVNEWFRAME_NODE,
JTI_SOFT_JNIPOPSYSTEMFRAME_NODE,
JTI_SOFT_FMOD_NODE,
JTI_SOFT_EXCEPTIONINFO_CALL_NODE,
JTI_SOFT_IDIV_NODE,
JTI_SOFT_IREM_NODE,
JTI_SOFT_LDIV_NODE,
@ -581,8 +580,6 @@ extern tree java_global_trees[JTI_MAX];
java_global_trees[JTI_SOFT_JNIPOPSYSTEMFRAME_NODE]
#define soft_fmod_node \
java_global_trees[JTI_SOFT_FMOD_NODE]
#define soft_exceptioninfo_call_node \
java_global_trees[JTI_SOFT_EXCEPTIONINFO_CALL_NODE]
#define soft_idiv_node \
java_global_trees[JTI_SOFT_IDIV_NODE]
#define soft_irem_node \
@ -1026,6 +1023,7 @@ extern tree build_instanceof PARAMS ((tree, tree));
extern tree create_label_decl PARAMS ((tree));
extern void push_labeled_block PARAMS ((tree));
extern tree prepare_eh_table_type PARAMS ((tree));
extern tree build_exception_object_ref PARAMS ((tree));
extern void java_set_exception_lang_code PARAMS ((void));
extern tree generate_name PARAMS ((void));
extern void pop_labeled_block PARAMS ((void));

View File

@ -2451,6 +2451,9 @@ generate_bytecode_insns (exp, target, state)
}
}
break;
case EXC_PTR_EXPR:
NOTE_PUSH (1); /* Pushed by exception system. */
break;
case NEW_CLASS_EXPR:
{
tree class = TREE_TYPE (TREE_TYPE (exp));
@ -2527,11 +2530,6 @@ generate_bytecode_insns (exp, target, state)
NOTE_POP (1);
break;
}
else if (exp == soft_exceptioninfo_call_node)
{
NOTE_PUSH (1); /* Pushed by exception system. */
break;
}
for ( ; x != NULL_TREE; x = TREE_CHAIN (x))
{
generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);

View File

@ -661,14 +661,6 @@ typedef struct _jdeplist {
build_new_invocation (wfl_string_buffer, \
(ARG ? build_tree_list (NULL, (ARG)) : NULL_TREE))
/* For exception handling, build diverse function calls */
#define BUILD_ASSIGN_EXCEPTION_INFO(WHERE, TO) \
{ \
(WHERE) = build (MODIFY_EXPR, void_type_node, (TO), \
soft_exceptioninfo_call_node); \
TREE_SIDE_EFFECTS (WHERE) = 1; \
}
#define BUILD_THROW(WHERE, WHAT) \
{ \
(WHERE) = \

View File

@ -1885,9 +1885,9 @@ catch_clause_parameter:
declared initialized by the appropriate function
call */
tree ccpb = enter_block ();
tree init = build_assignment (ASSIGN_TK, $2.location,
TREE_PURPOSE ($3),
soft_exceptioninfo_call_node);
tree init = build_assignment
(ASSIGN_TK, $2.location, TREE_PURPOSE ($3),
build_exception_object_ref (ptr_type_node));
declare_local_variables (0, TREE_VALUE ($3),
build_tree_list (TREE_PURPOSE ($3),
init));
@ -7124,9 +7124,6 @@ source_end_java_method ()
java_parser_context_save_global ();
lineno = ctxp->last_ccb_indent1;
/* Set EH language codes */
java_set_exception_lang_code ();
/* Turn function bodies with only a NOP expr null, so they don't get
generated at all and we won't get warnings when using the -W
-Wall flags. */
@ -7148,8 +7145,6 @@ source_end_java_method ()
if (! flag_emit_class_files && ! flag_emit_xref)
{
lineno = DECL_SOURCE_LINE_LAST (fndecl);
/* Emit catch-finally clauses */
emit_handlers ();
expand_function_end (input_filename, lineno, 0);
/* Run the optimizers and output assembler code for this function. */
@ -8405,7 +8400,7 @@ build_dot_class_method (class)
/* We initialize the variable with the exception handler. */
catch = build (MODIFY_EXPR, NULL_TREE, catch_clause_param,
soft_exceptioninfo_call_node);
build_exception_object_ref (ptr_type_node));
add_stmt_to_block (catch_block, NULL_TREE, catch);
/* We add the statement throwing the new exception */
@ -12609,7 +12604,7 @@ try_reference_assignconv (lhs_type, rhs)
else if (valid_ref_assignconv_cast_p (rhs_type, lhs_type, 0))
new_rhs = rhs;
/* This is a magic assignment that we process differently */
else if (rhs == soft_exceptioninfo_call_node)
else if (TREE_CODE (rhs) == EXC_PTR_EXPR)
new_rhs = rhs;
}
return new_rhs;

View File

@ -213,12 +213,6 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
cross_jump_death_matters = (cross_jump == 2);
max_uid = init_label_info (f) + 1;
/* If we are performing cross jump optimizations, then initialize
tables mapping UIDs to EH regions to avoid incorrect movement
of insns from one EH region to another. */
if (flag_exceptions && cross_jump)
init_insn_eh_region (f, max_uid);
if (! mark_labels_only)
delete_barrier_successors (f);
@ -237,8 +231,6 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL)
LABEL_NUSES (XEXP (insn, 0))++;
check_exception_handler_labels ();
/* Keep track of labels used for marking handlers for exception
regions; they cannot usually be deleted. */
@ -251,9 +243,6 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
if (mark_labels_only)
goto end;
if (! minimal)
exception_optimize ();
last_insn = delete_unreferenced_labels (f);
if (noop_moves)
@ -1444,13 +1433,6 @@ find_cross_jump (e1, e2, minimum, f1, f2)
if (i2 == 0 || GET_CODE (i1) != GET_CODE (i2))
break;
/* Avoid moving insns across EH regions if either of the insns
can throw. */
if (flag_exceptions
&& (flag_non_call_exceptions || GET_CODE (i1) == CALL_INSN)
&& !in_same_eh_region (i1, i2))
break;
p1 = PATTERN (i1);
p2 = PATTERN (i2);

View File

@ -114,28 +114,27 @@ GCC_3.0 {
__gcc_bcmp
# EH symbols
__default_terminate
_Unwind_DeleteException
_Unwind_ForcedUnwind
_Unwind_GetGR
_Unwind_GetIP
_Unwind_GetLanguageSpecificData
_Unwind_GetRegionStart
_Unwind_RaiseException
_Unwind_Resume
_Unwind_SetGR
_Unwind_SetIP
__deregister_frame
__deregister_frame_info
__eh_alloc
__eh_free
__eh_rtime_match
__frame_state_for
__get_dynamic_handler_chain
__get_eh_context
__get_eh_info
__get_eh_table_language
__get_eh_table_version
__register_frame
__register_frame_info
__register_frame_info_table
__register_frame_table
__rethrow
__sjpopnthrow
__sjthrow
__terminate
__terminate_set_func
__throw
__throw_type_match
__unwinding_cleanup
# SjLj EH symbols
_Unwind_SjLj_Register
_Unwind_SjLj_Unregister
_Unwind_SjLj_RaiseException
_Unwind_SjLj_ForcedUnwind
_Unwind_SjLj_Resume
}

File diff suppressed because it is too large Load Diff

View File

@ -2848,26 +2848,24 @@ You will not normally need to define this pattern unless you also define
@code{builtin_setjmp_setup}. The single argument is a pointer to the
@code{jmp_buf}.
@cindex @code{eh_epilogue} instruction pattern
@item @samp{eh_epilogue}
@cindex @code{eh_return} instruction pattern
@item @samp{eh_return}
This pattern, if defined, affects the way @code{__builtin_eh_return},
and thence @code{__throw} are built. It is intended to allow communication
between the exception handling machinery and the normal epilogue code
for the target.
and thence the call frame exception handling library routines, are
built. It is intended to handle non-trivial actions needed along
the abnormal return path.
The pattern takes three arguments. The first is the exception context
pointer. This will have already been copied to the function return
register appropriate for a pointer; normally this can be ignored. The
second argument is an offset to be added to the stack pointer. It will
have been copied to some arbitrary call-clobbered hard reg so that it
will survive until after reload to when the normal epilogue is generated.
The final argument is the address of the exception handler to which
The pattern takes two arguments. The first is an offset to be applied
to the stack pointer. It will have been copied to some appropriate
location (typically @code{EH_RETURN_STACKADJ_RTX}) which will survive
until after reload to when the normal epilogue is generated.
The second argument is the address of the exception handler to which
the function should return. This will normally need to copied by the
pattern to some special register.
pattern to some special register or memory location.
This pattern must be defined if @code{RETURN_ADDR_RTX} does not yield
something that can be reliably and permanently modified, i.e. a fixed
hard register or a stack memory reference.
This pattern only needs to be defined if call frame exception handling
is to be used, and simple moves to @code{EH_RETURN_STACKADJ_RTX} and
@code{EH_RETURN_HANDLER_RTX} are not sufficient.
@cindex @code{prologue} instruction pattern
@item @samp{prologue}

View File

@ -14,8 +14,9 @@
# LIB1ASMFUNCS
# LIB1FUNCS_EXTRA
# LIB2FUNCS
# LIB2FUNCS_EH
# LIB2ADD
# LIB2ADDEH
# LIB2ADDEHDEP
# FPBIT
# FPBIT_FUNCS
# DPBIT
@ -79,7 +80,7 @@ make_compile='$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
libgcc1_c_dep='stmp-dirs $(srcdir)/libgcc1.c $(CONFIG_H)'
# Dependancies for libgcc2.c
libgcc2_c_dep='stmp-dirs $(srcdir)/libgcc2.c $(CONFIG_H) $(MACHMODE_H) longlong.h frame.h gbl-ctors.h config.status stmp-int-hdrs tsystem.h'
libgcc2_c_dep='stmp-dirs $(srcdir)/libgcc2.c $(CONFIG_H) $(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs tsystem.h'" $LIB2ADDEHDEP"
# Dependancies for fp-bit.c
fpbit_c_dep='stmp-dirs config.status tsystem.h'
@ -180,19 +181,6 @@ for name in $LIB2FUNCS; do
libgcc2_objs="$libgcc2_objs ${name}${objext}"
done
for name in $LIB2FUNCS_EH; do
for ml in $MULTILIBS; do
dir=`echo ${ml} | sed -e 's/;.*$//' -e 's/=/$(EQ)/g'`
flags=`echo ${ml} | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`;
out="libgcc/${dir}/${name}${objext}"
echo $out: $libgcc2_c_dep
echo " $gcc_compile" '$(MAYBE_USE_COLLECT2)' -fexceptions \
$flags -DL$name -c '$(srcdir)/libgcc2.c' -o $out
done
libgcc2_objs="$libgcc2_objs ${name}${objext}"
done
if [ "$FPBIT" ]; then
for name in $FPBIT_FUNCS; do
for ml in $MULTILIBS; do
@ -241,6 +229,24 @@ for file in $LIB2ADD; do
libgcc2_objs="$libgcc2_objs ${oname}${objext}"
done
for file in $LIB2ADDEH; do
name=`echo $file | sed -e 's/[.][cSo]$//' -e 's/[.]asm$//' -e 's/[.]txt$//'`
oname=`echo $name | sed -e 's,.*/,,'`
for ml in $MULTILIBS; do
dir=`echo ${ml} | sed -e 's/;.*$//' -e 's/=/$(EQ)/g'`
flags=`echo ${ml} | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`;
out="libgcc/${dir}/${oname}${objext}"
if [ ${name}.asm = ${file} ]; then
flags="$flags -xassembler-with-cpp"
fi
echo $out: stmp-dirs $file
echo " $gcc_compile" $flags -fexceptions -c $file -o $out
done
libgcc2_objs="$libgcc2_objs ${oname}${objext}"
done
# SHLIB_MKMAP
# SHLIB_MAPFILES
for ml in $MULTILIBS; do

View File

@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "tm_p.h"
#include "flags.h"
#include "function.h"
#include "except.h"
#include "expr.h"
#include "recog.h"
#include "reload.h"
@ -4758,12 +4759,9 @@ init_optabs ()
memset_libfunc = init_one_libfunc ("memset");
bzero_libfunc = init_one_libfunc ("bzero");
throw_libfunc = init_one_libfunc ("__throw");
rethrow_libfunc = init_one_libfunc ("__rethrow");
sjthrow_libfunc = init_one_libfunc ("__sjthrow");
sjpopnthrow_libfunc = init_one_libfunc ("__sjpopnthrow");
terminate_libfunc = init_one_libfunc ("__terminate");
eh_rtime_match_libfunc = init_one_libfunc ("__eh_rtime_match");
unwind_resume_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
? "_Unwind_SjLj_Resume"
: "_Unwind_Resume");
#ifndef DONT_USE_BUILTIN_SETJMP
setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
@ -4771,6 +4769,9 @@ init_optabs ()
setjmp_libfunc = init_one_libfunc ("setjmp");
longjmp_libfunc = init_one_libfunc ("longjmp");
#endif
unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
unwind_sjlj_unregister_libfunc
= init_one_libfunc ("_Unwind_SjLj_Unregister");
eqhf2_libfunc = init_one_libfunc ("__eqhf2");
nehf2_libfunc = init_one_libfunc ("__nehf2");

View File

@ -547,6 +547,11 @@ DEF_RTL_EXPR(RETURN, "return", "", 'x')
For an unconditional trap, make the condition (const_int 1). */
DEF_RTL_EXPR(TRAP_IF, "trap_if", "ee", 'x')
/* Placeholder for _Unwind_Resume before we know if a function call
or a branch is needed. Operand 1 is the exception region from
which control is flowing. */
DEF_RTL_EXPR(RESX, "resx", "i", 'x')
/* ----------------------------------------------------------------------
Primitive values for use in expressions.
---------------------------------------------------------------------- */

View File

@ -924,10 +924,6 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
/* Flag in a SYMBOL_REF for machine-specific purposes. */
#define SYMBOL_REF_FLAG(RTX) ((RTX)->volatil)
/* 1 in a SYMBOL_REF if it represents a symbol which might have to change
if its inlined or unrolled. */
#define SYMBOL_REF_NEED_ADJUST(RTX) ((RTX)->in_struct)
/* 1 means a SYMBOL_REF has been the library function in emit_library_call. */
#define SYMBOL_REF_USED(RTX) ((RTX)->used)

View File

@ -4072,12 +4072,11 @@ expand_decl_cleanup (decl, cleanup)
start_sequence ();
}
/* If this was optimized so that there is no exception region for the
cleanup, then mark the TREE_LIST node, so that we can later tell
if we need to call expand_eh_region_end. */
if (! using_eh_for_cleanups_p
|| expand_eh_region_start_tree (decl, cleanup))
if (! using_eh_for_cleanups_p)
TREE_ADDRESSABLE (t) = 1;
else
expand_eh_region_start ();
/* If that started a new EH region, we're in a new block. */
thisblock = block_stack;
@ -4106,82 +4105,6 @@ expand_decl_cleanup (decl, cleanup)
}
return 1;
}
/* Arrange for the top element of the dynamic cleanup chain to be
popped if we exit the current binding contour. DECL is the
associated declaration, if any, otherwise NULL_TREE. If the
current contour is left via an exception, then __sjthrow will pop
the top element off the dynamic cleanup chain. The code that
avoids doing the action we push into the cleanup chain in the
exceptional case is contained in expand_cleanups.
This routine is only used by expand_eh_region_start, and that is
the only way in which an exception region should be started. This
routine is only used when using the setjmp/longjmp codegen method
for exception handling. */
int
expand_dcc_cleanup (decl)
tree decl;
{
struct nesting *thisblock;
tree cleanup;
/* Error if we are not in any block. */
if (cfun == 0 || block_stack == 0)
return 0;
thisblock = block_stack;
/* Record the cleanup for the dynamic handler chain. */
cleanup = make_node (POPDCC_EXPR);
/* Add the cleanup in a manner similar to expand_decl_cleanup. */
thisblock->data.block.cleanups
= tree_cons (decl, cleanup, thisblock->data.block.cleanups);
/* If this block has a cleanup, it belongs in stack_block_stack. */
stack_block_stack = thisblock;
return 1;
}
/* Arrange for the top element of the dynamic handler chain to be
popped if we exit the current binding contour. DECL is the
associated declaration, if any, otherwise NULL_TREE. If the current
contour is left via an exception, then __sjthrow will pop the top
element off the dynamic handler chain. The code that avoids doing
the action we push into the handler chain in the exceptional case
is contained in expand_cleanups.
This routine is only used by expand_eh_region_start, and that is
the only way in which an exception region should be started. This
routine is only used when using the setjmp/longjmp codegen method
for exception handling. */
int
expand_dhc_cleanup (decl)
tree decl;
{
struct nesting *thisblock;
tree cleanup;
/* Error if we are not in any block. */
if (cfun == 0 || block_stack == 0)
return 0;
thisblock = block_stack;
/* Record the cleanup for the dynamic handler chain. */
cleanup = make_node (POPDHC_EXPR);
/* Add the cleanup in a manner similar to expand_decl_cleanup. */
thisblock->data.block.cleanups
= tree_cons (decl, cleanup, thisblock->data.block.cleanups);
/* If this block has a cleanup, it belongs in stack_block_stack. */
stack_block_stack = thisblock;
return 1;
}
/* DECL is an anonymous union. CLEANUP is a cleanup for DECL.
DECL_ELTS is the list of elements that belong to DECL's type.
@ -4286,20 +4209,8 @@ expand_cleanups (list, dont_do, in_fixup, reachable)
expand_cleanups (TREE_VALUE (tail), dont_do, in_fixup, reachable);
else
{
if (! in_fixup)
{
tree cleanup = TREE_VALUE (tail);
/* See expand_d{h,c}c_cleanup for why we avoid this. */
if (TREE_CODE (cleanup) != POPDHC_EXPR
&& TREE_CODE (cleanup) != POPDCC_EXPR
/* See expand_eh_region_start_tree for this case. */
&& ! TREE_ADDRESSABLE (tail))
{
cleanup = protect_with_terminate (cleanup);
expand_eh_region_end (cleanup);
}
}
if (! in_fixup && using_eh_for_cleanups_p)
expand_eh_region_end_cleanup (TREE_VALUE (tail));
if (reachable)
{
@ -4312,19 +4223,18 @@ expand_cleanups (list, dont_do, in_fixup, reachable)
times, the control paths are non-overlapping so the
cleanups will not be executed twice. */
/* We may need to protect fixups with rethrow regions. */
int protect = (in_fixup && ! TREE_ADDRESSABLE (tail));
/* We may need to protect from outer cleanups. */
if (in_fixup && using_eh_for_cleanups_p)
{
expand_eh_region_start ();
if (protect)
expand_fixup_region_start ();
expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0);
expand_eh_region_end_fixup (TREE_VALUE (tail));
}
else
expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0);
/* The cleanup might contain try-blocks, so we have to
preserve our current queue. */
push_ehqueue ();
expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0);
pop_ehqueue ();
if (protect)
expand_fixup_region_end (TREE_VALUE (tail));
free_temp_slots ();
}
}

View File

@ -2505,6 +2505,54 @@ You only need to define this macro if the default is incorrect, and you
want to support call frame debugging information like that provided by
DWARF 2.
@findex EH_RETURN_DATA_REGNO
@item EH_RETURN_DATA_REGNO (@var{N})
A C expression whose value is the @var{N}th register number used for
data by exception handlers, or @code{INVALID_REGNUM} if fewer than
@var{N} registers are usable.
The exception handling library routines communicate with the exception
handlers via a set of agreed upon registers. Ideally these registers
should be call-clobbered; it is possible to use call-saved registers,
but may negatively impact code size. The target must support at least
2 data registers, but should define 4 if there are enough free registers.
You must define this macro if you want to support call frame exception
handling like that provided by DWARF 2.
@findex EH_RETURN_STACKADJ_RTX
@item EH_RETURN_STACKADJ_RTX
A C expression whose value is RTL representing a location in which
to store a stack adjustment to be applied before function return.
This is used to unwind the stack to an exception handler's call frame.
It will be assigned zero on code paths that return normally.
Typically this is a call-clobbered hard register that is otherwise
untouched by the epilogue, but could also be a stack slot.
You must define this macro if you want to support call frame exception
handling like that provided by DWARF 2.
@findex EH_RETURN_HANDLER_RTX
@item EH_RETURN_HANDLER_RTX
A C expression whose value is RTL representing a location in which
to store the address of an exception handler to which we should
return. It will not be assigned on code paths that return normally.
Typically this is the location in the call frame at which the normal
return address is stored. For targets that return by popping an
address off the stack, this might be a memory address just below
the @emph{target} call frame rather than inside the current call
frame. @code{EH_RETURN_STACKADJ_RTX} will have already been assigned,
so it may be used to calculate the location of the target call frame.
Some targets have more complex requirements than storing to an
address calculable during initial code generation. In that case
the @code{eh_return} instruction pattern should be used instead.
If you want to support call frame exception handling, you must
define either this macro or the @code{eh_return} instruction pattern.
@findex SMALL_STACK
@item SMALL_STACK
Define this macro if the stack size for the target is very small. This

View File

@ -252,6 +252,7 @@ enum dump_file_index
{
DFI_rtl,
DFI_sibling,
DFI_eh,
DFI_jump,
DFI_cse,
DFI_addressof,
@ -289,7 +290,7 @@ enum dump_file_index
Remaining -d letters:
" h o q u "
" o q u "
" H K OPQ TUVW YZ"
*/
@ -297,6 +298,7 @@ struct dump_file_info dump_file[DFI_MAX] =
{
{ "rtl", 'r', 0, 0, 0 },
{ "sibling", 'i', 0, 0, 0 },
{ "eh", 'h', 0, 0, 0 },
{ "jump", 'j', 0, 0, 0 },
{ "cse", 's', 0, 0, 0 },
{ "addressof", 'F', 0, 0, 0 },
@ -2162,9 +2164,9 @@ compile_file (name)
init_regs ();
init_alias_once ();
init_decl_processing ();
init_eh ();
init_optabs ();
init_stmt ();
init_eh ();
init_loop ();
init_reload ();
init_function_once ();
@ -2402,14 +2404,6 @@ compile_file (name)
loop above. */
output_func_start_profiler ();
/* Now that all possible functions have been output, we can dump
the exception table. */
#ifndef IA64_UNWIND_INFO
output_exception_table ();
#endif
free_exception_table ();
check_global_declarations (vec, len);
/* Clean up. */
@ -2805,6 +2799,11 @@ rest_of_compilation (decl)
close_dump_file (DFI_rtl, print_rtl, insns);
}
/* Convert from NOTE_INSN_EH_REGION style notes, and do other
sorts of eh initialization. Delay this until after the
initial rtl dump so that we can see the original nesting. */
convert_from_eh_region_ranges ();
/* If function is inline, and we don't yet know whether to
compile it by itself, defer decision till end of compilation.
finish_compilation will call rest_of_compilation again
@ -2884,9 +2883,6 @@ rest_of_compilation (decl)
if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
goto exit_rest_of_compilation;
/* Emit code to get eh context, if needed. */
emit_eh_context ();
/* We may have potential sibling or tail recursion sites. Select one
(of possibly multiple) methods of performing the call. */
if (flag_optimize_sibling_calls)
@ -2900,6 +2896,19 @@ rest_of_compilation (decl)
timevar_pop (TV_JUMP);
}
/* Complete generation of exception handling code. */
find_exception_handler_labels ();
if (doing_eh (0))
{
timevar_push (TV_JUMP);
open_dump_file (DFI_eh, decl);
finish_eh_generation ();
close_dump_file (DFI_eh, print_rtl, get_insns ());
timevar_pop (TV_JUMP);
}
#ifdef FINALIZE_PIC
/* If we are doing position-independent code generation, now
is the time to output special prologues and epilogues.
@ -2923,9 +2932,6 @@ rest_of_compilation (decl)
/* Instantiate all virtual registers. */
instantiate_virtual_regs (current_function_decl, insns);
/* Find all the EH handlers. */
find_exception_handler_labels ();
open_dump_file (DFI_jump, decl);
/* Always do one jump optimization pass to ensure that JUMP_LABEL fields
@ -3679,6 +3685,12 @@ rest_of_compilation (decl)
}
#endif
#ifndef STACK_REGS
/* ??? Do this before shorten branches so that we aren't creating
insns too late and fail sanity checks in final. */
convert_to_eh_region_ranges ();
#endif
/* Shorten branches.
Note this must run before reg-stack because of death note (ab)use
@ -3697,6 +3709,8 @@ rest_of_compilation (decl)
timevar_pop (TV_REG_STACK);
ggc_collect ();
convert_to_eh_region_ranges ();
#endif
current_function_nothrow = nothrow_function_p ();
@ -3728,6 +3742,9 @@ rest_of_compilation (decl)
final (insns, asm_out_file, optimize, 0);
final_end_function (insns, asm_out_file, optimize);
assemble_end_function (decl, fnname);
output_function_exception_table ();
if (! quiet_flag)
fflush (asm_out_file);

View File

@ -770,17 +770,6 @@ DEFTREECODE (TRY_FINALLY_EXPR, "try_finally", 'e', 2)
Operand 1 is the rtx for a variable in which to store the address
of where the subroutine should return to. */
DEFTREECODE (GOTO_SUBROUTINE_EXPR, "goto_subroutine", 'e', 2)
/* Pop the top element off the dynamic handler chain. Used in
conjunction with setjmp/longjmp based exception handling, see
except.c for more details. This is meant to be used only by the
exception handling backend, expand_dhc_cleanup specifically. */
DEFTREECODE (POPDHC_EXPR, "popdhc_expr", 's', 0)
/* Pop the top element off the dynamic cleanup chain. Used in
conjunction with the exception handling. This is meant to be used
only by the exception handling backend. */
DEFTREECODE (POPDCC_EXPR, "popdcc_expr", 's', 0)
/* These types of expressions have no useful value,
and always have side effects. */
@ -834,6 +823,10 @@ DEFTREECODE (EXPR_WITH_FILE_LOCATION, "expr_with_file_location", 'e', 3)
Operand 1 contains the case values. The way they're organized is
front-end implementation defined. */
DEFTREECODE (SWITCH_EXPR, "switch_expr", 'e', 2)
/* The exception object from the runtime. */
DEFTREECODE (EXC_PTR_EXPR, "exc_ptr_expr", 'e', 0)
/*
Local variables:
mode:c

View File

@ -1,6 +1,5 @@
/* Subroutines needed for unwinding stack frames for exception handling. */
/* Compile this one with gcc. */
/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@cygnus.com>.
This file is part of GNU CC.
@ -29,6 +28,129 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "tconfig.h"
#include "tsystem.h"
#include "unwind-dw2-fde.h"
#include "gthr.h"
static struct object *objects;
#ifdef __GTHREAD_MUTEX_INIT
static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT;
#else
static __gthread_mutex_t object_mutex;
#endif
#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
static void
init_object_mutex (void)
{
__GTHREAD_MUTEX_INIT_FUNCTION (&object_mutex);
}
static void
init_object_mutex_once (void)
{
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
__gthread_once (&once, init_object_mutex);
}
#else
#define init_object_mutex_once()
#endif
/* Called from crtbegin.o to register the unwind info for an object. */
void
__register_frame_info (void *begin, struct object *ob)
{
ob->pc_begin = ob->pc_end = 0;
ob->fde_begin = begin;
ob->fde_array = 0;
ob->count = 0;
init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
ob->next = objects;
objects = ob;
__gthread_mutex_unlock (&object_mutex);
}
void
__register_frame (void *begin)
{
struct object *ob = (struct object *) malloc (sizeof (struct object));
__register_frame_info (begin, ob);
}
/* Similar, but BEGIN is actually a pointer to a table of unwind entries
for different translation units. Called from the file generated by
collect2. */
void
__register_frame_info_table (void *begin, struct object *ob)
{
ob->pc_begin = ob->pc_end = 0;
ob->fde_begin = begin;
ob->fde_array = begin;
ob->count = 0;
init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
ob->next = objects;
objects = ob;
__gthread_mutex_unlock (&object_mutex);
}
void
__register_frame_table (void *begin)
{
struct object *ob = (struct object *) malloc (sizeof (struct object));
__register_frame_info_table (begin, ob);
}
/* Called from crtbegin.o to deregister the unwind info for an object. */
void *
__deregister_frame_info (void *begin)
{
struct object **p;
init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
p = &objects;
while (*p)
{
if ((*p)->fde_begin == begin)
{
struct object *ob = *p;
*p = (*p)->next;
/* If we've run init_frame for this object, free the FDE array. */
if (ob->fde_array && ob->fde_array != begin)
free (ob->fde_array);
__gthread_mutex_unlock (&object_mutex);
return (void *) ob;
}
p = &((*p)->next);
}
__gthread_mutex_unlock (&object_mutex);
abort ();
}
void
__deregister_frame (void *begin)
{
free (__deregister_frame_info (begin));
}
/* Sorting an array of FDEs by address.
(Ideally we would have the linker sort the FDEs so we don't have to do
it at run time. But the linkers are not yet prepared for this.) */
@ -56,6 +178,12 @@ typedef struct fde_accumulator
fde_vector erratic;
} fde_accumulator;
static inline saddr
fde_compare (fde *x, fde *y)
{
return (saddr)x->pc_begin - (saddr)y->pc_begin;
}
static inline int
start_fde_sort (fde_accumulator *accu, size_t count)
{
@ -241,97 +369,174 @@ end_fde_sort (fde_accumulator *accu, size_t count)
return accu->linear.array;
}
/* Called from crtbegin.o to register the unwind info for an object. */
void
__register_frame_info (void *begin, struct object *ob)
static size_t
count_fdes (fde *this_fde)
{
ob->fde_begin = begin;
size_t count;
ob->pc_begin = ob->pc_end = 0;
ob->fde_array = 0;
ob->count = 0;
for (count = 0; this_fde->length != 0; this_fde = next_fde (this_fde))
/* Skip CIEs and omitted link-once FDE entries. */
if (this_fde->CIE_delta != 0 && this_fde->pc_begin != 0)
++count;
init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
ob->next = objects;
objects = ob;
__gthread_mutex_unlock (&object_mutex);
return count;
}
void
__register_frame (void *begin)
static void
add_fdes (fde *this_fde, fde_accumulator *accu, void **beg_ptr, void **end_ptr)
{
struct object *ob = (struct object *) malloc (sizeof (struct object));
__register_frame_info (begin, ob);
}
void *pc_begin = *beg_ptr;
void *pc_end = *end_ptr;
/* Similar, but BEGIN is actually a pointer to a table of unwind entries
for different translation units. Called from the file generated by
collect2. */
void
__register_frame_info_table (void *begin, struct object *ob)
{
ob->fde_begin = begin;
ob->fde_array = begin;
ob->pc_begin = ob->pc_end = 0;
ob->count = 0;
init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
ob->next = objects;
objects = ob;
__gthread_mutex_unlock (&object_mutex);
}
void
__register_frame_table (void *begin)
{
struct object *ob = (struct object *) malloc (sizeof (struct object));
__register_frame_info_table (begin, ob);
}
/* Called from crtbegin.o to deregister the unwind info for an object. */
void *
__deregister_frame_info (void *begin)
{
struct object **p;
init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
p = &objects;
while (*p)
for (; this_fde->length != 0; this_fde = next_fde (this_fde))
{
if ((*p)->fde_begin == begin)
{
struct object *ob = *p;
*p = (*p)->next;
/* Skip CIEs and linked once FDE entries. */
if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
continue;
/* If we've run init_frame for this object, free the FDE array. */
if (ob->fde_array && ob->fde_array != begin)
free (ob->fde_array);
fde_insert (accu, this_fde);
__gthread_mutex_unlock (&object_mutex);
return (void *) ob;
}
p = &((*p)->next);
if (this_fde->pc_begin < pc_begin)
pc_begin = this_fde->pc_begin;
if (this_fde->pc_begin + this_fde->pc_range > pc_end)
pc_end = this_fde->pc_begin + this_fde->pc_range;
}
__gthread_mutex_unlock (&object_mutex);
abort ();
*beg_ptr = pc_begin;
*end_ptr = pc_end;
}
void
__deregister_frame (void *begin)
static fde *
search_fdes (fde *this_fde, void *pc)
{
free (__deregister_frame_info (begin));
for (; this_fde->length != 0; this_fde = next_fde (this_fde))
{
/* Skip CIEs and linked once FDE entries. */
if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
continue;
if ((uaddr)((char *)pc - (char *)this_fde->pc_begin) < this_fde->pc_range)
return this_fde;
}
return NULL;
}
/* Set up a sorted array of pointers to FDEs for a loaded object. We
count up the entries before allocating the array because it's likely to
be faster. We can be called multiple times, should we have failed to
allocate a sorted fde array on a previous occasion. */
static void
frame_init (struct object* ob)
{
size_t count;
fde_accumulator accu;
void *pc_begin, *pc_end;
fde **array;
if (ob->pc_begin)
count = ob->count;
else if (ob->fde_array)
{
fde **p = ob->fde_array;
for (count = 0; *p; ++p)
count += count_fdes (*p);
}
else
count = count_fdes (ob->fde_begin);
ob->count = count;
if (!start_fde_sort (&accu, count) && ob->pc_begin)
return;
pc_begin = (void*)(uaddr)-1;
pc_end = 0;
if (ob->fde_array)
{
fde **p = ob->fde_array;
for (; *p; ++p)
add_fdes (*p, &accu, &pc_begin, &pc_end);
}
else
add_fdes (ob->fde_begin, &accu, &pc_begin, &pc_end);
array = end_fde_sort (&accu, count);
if (array)
ob->fde_array = array;
ob->pc_begin = pc_begin;
ob->pc_end = pc_end;
}
fde *
_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
{
struct object *ob;
size_t lo, hi;
init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
/* Linear search through the objects, to find the one containing the pc. */
for (ob = objects; ob; ob = ob->next)
{
if (ob->pc_begin == 0)
frame_init (ob);
if (pc >= ob->pc_begin && pc < ob->pc_end)
break;
}
if (ob == 0)
{
__gthread_mutex_unlock (&object_mutex);
return 0;
}
if (!ob->fde_array || (void *)ob->fde_array == (void *)ob->fde_begin)
frame_init (ob);
if (ob->fde_array && (void *)ob->fde_array != (void *)ob->fde_begin)
{
__gthread_mutex_unlock (&object_mutex);
/* Standard binary search algorithm. */
for (lo = 0, hi = ob->count; lo < hi; )
{
size_t i = (lo + hi) / 2;
fde *f = ob->fde_array[i];
if (pc < f->pc_begin)
hi = i;
else if (pc >= f->pc_begin + f->pc_range)
lo = i + 1;
else
return f;
}
}
else
{
/* Long slow labourious linear search, cos we've no memory. */
fde *f;
if (ob->fde_array)
{
fde **p = ob->fde_array;
do
{
f = search_fdes (*p, pc);
if (f)
break;
p++;
}
while (*p);
}
else
f = search_fdes (ob->fde_begin, pc);
__gthread_mutex_unlock (&object_mutex);
return f;
}
return 0;
}

120
gcc/unwind-dw2-fde.h Normal file
View File

@ -0,0 +1,120 @@
/* Subroutines needed for unwinding stack frames for exception handling. */
/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@cygnus.com>.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file into combinations with other programs,
and to distribute those combinations without any restriction coming
from the use of this file. (The General Public License restrictions
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combine
executable.)
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Describes data used to hold onto one shared object or object file. */
struct object
{
void *pc_begin;
void *pc_end;
struct dwarf_fde *fde_begin;
struct dwarf_fde **fde_array;
size_t count;
struct object *next;
};
struct dwarf_eh_bases
{
void *tbase;
void *dbase;
void *func;
};
extern void __register_frame_info (void *, struct object *);
extern void __register_frame (void *);
extern void __register_frame_info_table (void *, struct object *);
extern void __register_frame_table (void *);
extern void *__deregister_frame_info (void *);
extern void __deregister_frame (void *);
typedef int sword __attribute__ ((mode (SI)));
typedef unsigned int uword __attribute__ ((mode (SI)));
typedef unsigned int uaddr __attribute__ ((mode (pointer)));
typedef int saddr __attribute__ ((mode (pointer)));
typedef unsigned char ubyte;
/* Terminology:
CIE - Common Information Element
FDE - Frame Descriptor Element
There is one per function, and it describes where the function code
is located, and what the register lifetimes and stack layout are
within the function.
The data structures are defined in the DWARF specfication, although
not in a very readable way (see LITERATURE).
Every time an exception is thrown, the code needs to locate the FDE
for the current function, and starts to look for exception regions
from that FDE. This works in a two-level search:
a) in a linear search, find the shared image (i.e. DLL) containing
the PC
b) using the FDE table for that shared object, locate the FDE using
binary search (which requires the sorting). */
/* The first few fields of a CIE. The CIE_id field is 0 for a CIE,
to distinguish it from a valid FDE. FDEs are aligned to an addressing
unit boundary, but the fields within are unaligned. */
struct dwarf_cie
{
uword length;
sword CIE_id;
ubyte version;
unsigned char augmentation[];
} __attribute__ ((packed, aligned (__alignof__ (void *))));
/* The first few fields of an FDE. */
struct dwarf_fde
{
uword length;
sword CIE_delta;
void * pc_begin;
uaddr pc_range;
} __attribute__ ((packed, aligned (__alignof__ (void *))));
typedef struct dwarf_fde fde;
/* Locate the CIE for a given FDE. */
static inline struct dwarf_cie *
get_cie (struct dwarf_fde *f)
{
return (void *)&f->CIE_delta - f->CIE_delta;
}
static inline fde *
next_fde (fde *f)
{
return (fde *)((char *)f + f->length + sizeof (f->length));
}
extern fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *);

1217
gcc/unwind-dw2.c Normal file

File diff suppressed because it is too large Load Diff

259
gcc/unwind-sjlj.c Normal file
View File

@ -0,0 +1,259 @@
/* DWARF2 exception handling and frame unwind runtime interface routines.
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "tconfig.h"
#include "tsystem.h"
#include "unwind.h"
#include "gthr.h"
#if USING_SJLJ_EXCEPTIONS
#ifdef DONT_USE_BUILTIN_SETJMP
#include <setjmp.h>
#else
#define setjmp __builtin_setjmp
#define longjmp __builtin_longjmp
#endif
/* This structure is allocated on the stack of the target function.
This must match the definition created in except.c:init_eh. */
struct SjLj_Function_Context
{
/* This is the chain through all registered contexts. It is
filled in by _Unwind_SjLj_Register. */
struct SjLj_Function_Context *prev;
/* This is assigned in by the target function before every call
to the index of the call site in the lsda. It is assigned by
the personality routine to the landing pad index. */
int call_site;
/* This is how data is returned from the personality routine to
the target function's handler. */
_Unwind_Word data[4];
/* These are filled in once by the target function before any
exceptions are expected to be handled. */
_Unwind_Personality_Fn personality;
void *lsda;
#ifdef DONT_USE_BUILTIN_SETJMP
/* We don't know what sort of alignment requirements the system
jmp_buf has. We over estimated in except.c, and now we have
to match that here just in case the system *didn't* have more
restrictive requirements. */
jmp_buf jbuf __attribute__((aligned));
#else
void *jbuf[];
#endif
};
struct _Unwind_Context
{
struct SjLj_Function_Context *fc;
};
typedef struct
{
_Unwind_Personality_Fn personality;
} _Unwind_FrameState;
/* Manage the chain of registered function contexts. */
/* Single threaded fallback chain. */
static struct SjLj_Function_Context *fc_static;
#if __GTHREADS
static __gthread_key_t fc_key;
static int use_fc_key = -1;
static void
fc_key_dtor (void *ptr)
{
__gthread_key_dtor (fc_key, ptr);
}
static void
fc_key_init (void)
{
use_fc_key = __gthread_key_create (&fc_key, fc_key_dtor) == 0;
}
static void
fc_key_init_once (void)
{
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
if (__gthread_once (&once, fc_key_init) != 0 || use_fc_key < 0)
use_fc_key = 0;
}
#endif
void
_Unwind_SjLj_Register (struct SjLj_Function_Context *fc)
{
#if __GTHREADS
if (use_fc_key < 0)
fc_key_init_once ();
if (use_fc_key)
{
fc->prev = __gthread_getspecific (fc_key);
__gthread_setspecific (fc_key, fc);
}
else
#endif
{
fc->prev = fc_static;
fc_static = fc;
}
}
static inline struct SjLj_Function_Context *
_Unwind_SjLj_GetContext (void)
{
#if __GTHREADS
if (use_fc_key < 0)
fc_key_init_once ();
if (use_fc_key)
return __gthread_getspecific (fc_key);
#endif
return fc_static;
}
static inline void
_Unwind_SjLj_SetContext (struct SjLj_Function_Context *fc)
{
#if __GTHREADS
if (use_fc_key < 0)
fc_key_init_once ();
if (use_fc_key)
__gthread_setspecific (fc_key, fc);
else
#endif
fc_static = fc;
}
void
_Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc)
{
_Unwind_SjLj_SetContext (fc->prev);
}
/* Get/set the return data value at INDEX in CONTEXT. */
_Unwind_Word
_Unwind_GetGR (struct _Unwind_Context *context, int index)
{
return context->fc->data[index];
}
void
_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
{
context->fc->data[index] = val;
}
/* Get the call-site index as saved in CONTEXT. */
_Unwind_Ptr
_Unwind_GetIP (struct _Unwind_Context *context)
{
return context->fc->call_site + 1;
}
/* Set the return landing pad index in CONTEXT. */
void
_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
{
context->fc->call_site = val - 1;
}
void *
_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
{
return context->fc->lsda;
}
_Unwind_Ptr
_Unwind_GetRegionStart (struct _Unwind_Context *context)
{
return 0;
}
static inline _Unwind_Reason_Code
uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
{
if (context->fc == NULL)
{
fs->personality = NULL;
return _URC_END_OF_STACK;
}
else
{
fs->personality = context->fc->personality;
return _URC_NO_REASON;
}
}
static inline void
uw_update_context (struct _Unwind_Context *context,
_Unwind_FrameState *fs __attribute__((unused)) )
{
context->fc = context->fc->prev;
}
static inline void
uw_init_context (struct _Unwind_Context *context)
{
context->fc = _Unwind_SjLj_GetContext ();
}
/* ??? There appear to be bugs in integrate.c wrt __builtin_longjmp and
virtual-stack-vars. An inline version of this segfaults on Sparc. */
#define uw_install_context(CURRENT, TARGET) \
do { \
_Unwind_SjLj_SetContext ((TARGET)->fc); \
longjmp ((TARGET)->fc->jbuf, 1); \
} while (0)
static inline _Unwind_Ptr
uw_identify_context (struct _Unwind_Context *context)
{
return (_Unwind_Ptr) context->fc;
}
/* Play games with unwind symbols so that we can have call frame
and sjlj symbols in the same shared library. Not that you can
use them simultaneously... */
#define _Unwind_RaiseException _Unwind_SjLj_RaiseException
#define _Unwind_ForcedUnwind _Unwind_SjLj_ForcedUnwind
#define _Unwind_Resume _Unwind_SjLj_Resume
#include "unwind.inc"
#endif /* USING_SJLJ_EXCEPTIONS */

166
gcc/unwind.h Normal file
View File

@ -0,0 +1,166 @@
/* Exception handling and frame unwind runtime interface routines.
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This is derived from the C++ ABI for IA-64. Where we diverge
for cross-architecture compatibility are noted with "@@@". */
#ifdef __cplusplus
extern "C" {
#endif
/* Level 1: Base ABI */
/* @@@ The IA-64 ABI uses uint64 throughout. Most places this is
inefficient for 32-bit and smaller machines. */
typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
/* @@@ The IA-64 ABI uses a 64-bit word to identify the producer and
consumer of an exception. We'll go along with this for now even on
32-bit machines. We'll need to provide some other option for
16-bit machines and for machines with > 8 bits per byte. */
typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
/* The unwind interface uses reason codes in several contexts to
identify the reasons for failures or other actions. */
typedef enum
{
_URC_NO_REASON = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
_URC_FATAL_PHASE2_ERROR = 2,
_URC_FATAL_PHASE1_ERROR = 3,
_URC_NORMAL_STOP = 4,
_URC_END_OF_STACK = 5,
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8
} _Unwind_Reason_Code;
/* The unwind interface uses a pointer to an exception header object
as its representation of an exception being thrown. In general, the
full representation of an exception object is language- and
implementation-specific, but it will be prefixed by a header
understood by the unwind interface. */
struct _Unwind_Exception;
typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
struct _Unwind_Exception *);
struct _Unwind_Exception
{
_Unwind_Exception_Class exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
_Unwind_Word private_1;
_Unwind_Word private_2;
/* @@@ The IA-64 ABI says that this structure must be double-word aligned.
Taking that literally does not make much sense generically. Instead we
provide the maximum alignment required by any type for the machine. */
} __attribute__((__aligned__));
/* The ACTIONS argument to the personality routine is a bitwise OR of one
or more of the following constants. */
typedef int _Unwind_Action;
#define _UA_SEARCH_PHASE 1
#define _UA_CLEANUP_PHASE 2
#define _UA_HANDLER_FRAME 4
#define _UA_FORCE_UNWIND 8
/* This is an opaque type used to refer to a system-specific data
structure used by the system unwinder. This context is created and
destroyed by the system, and passed to the personality routine
during unwinding. */
struct _Unwind_Context;
/* Raise an exception, passing along the given exception object. */
extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *);
/* Raise an exception for forced unwinding. */
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
(int, _Unwind_Action, _Unwind_Exception_Class,
struct _Unwind_Exception *, struct _Unwind_Context *, void *);
extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *,
_Unwind_Stop_Fn,
void *);
/* Helper to invoke the exception_cleanup routine. */
extern void _Unwind_DeleteException (struct _Unwind_Exception *);
/* Resume propagation of an existing exception. This is used after
e.g. executing cleanup code, and not to implement rethrowing. */
extern void _Unwind_Resume (struct _Unwind_Exception *);
/* These functions are used for communicating information about the unwind
context (i.e. the unwind descriptors and the user register state) between
the unwind library and the personality routine and landing pad. Only
selected registers maybe manipulated. */
extern _Unwind_Word _Unwind_GetGR (struct _Unwind_Context *, int);
extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word);
extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *);
extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr);
extern void *_Unwind_GetLanguageSpecificData (struct _Unwind_Context *);
extern _Unwind_Ptr _Unwind_GetRegionStart (struct _Unwind_Context *);
/* The personality routine is the function in the C++ (or other language)
runtime library which serves as an interface between the system unwind
library and language-specific exception handling semantics. It is
specific to the code fragment described by an unwind info block, and
it is always referenced via the pointer in the unwind info block, and
hence it has no ABI-specified name.
Note that this implies that two different C++ implementations can
use different names, and have different contents in the language
specific data area. Moreover, that the language specific data
area contains no version info because name of the function invoked
provides more effective versioning by detecting at link time the
lack of code to handle the different data format. */
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)
(int, _Unwind_Action, _Unwind_Exception_Class,
struct _Unwind_Exception *, struct _Unwind_Context *);
/* @@@ The following alternate entry points are for setjmp/longjmp
based unwinding. */
struct SjLj_Function_Context;
extern void _Unwind_SjLj_Register (struct SjLj_Function_Context *);
extern void _Unwind_SjLj_Unregister (struct SjLj_Function_Context *);
extern _Unwind_Reason_Code _Unwind_SjLj_RaiseException
(struct _Unwind_Exception *);
extern _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind
(struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
extern void _Unwind_SjLj_Resume (struct _Unwind_Exception *);
#ifdef __cplusplus
}
#endif

232
gcc/unwind.inc Normal file
View File

@ -0,0 +1,232 @@
/* Exception handling and frame unwind runtime interface routines.
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This is derived from the C++ ABI for IA-64. Where we diverge
for cross-architecture compatibility are noted with "@@@".
This file is included from unwind-dw2.c or unwind-ia64.c. */
/* Subroutine of _Unwind_RaiseException also invoked from _Unwind_Resume.
Unwind the stack calling the personality routine to find both the
exception handler and intermediary cleanup code. We'll only locate
the first such frame here. Cleanup code will call back into
_Unwind_Resume and we'll continue Phase 2 there. */
static _Unwind_Reason_Code
_Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc,
struct _Unwind_Context *context)
{
_Unwind_Reason_Code code;
while (1)
{
_Unwind_FrameState fs;
int match_handler;
code = uw_frame_state_for (context, &fs);
/* Identify when we've reached the designated handler context. */
match_handler = (uw_identify_context (context) == exc->private_2
? _UA_HANDLER_FRAME : 0);
if (code != _URC_NO_REASON)
/* Some error encountered. Ususally the unwinder doesn't
diagnose these and merely crashes. */
return _URC_FATAL_PHASE2_ERROR;
/* Unwind successful. Run the personality routine, if any. */
if (fs.personality)
{
code = (*fs.personality) (1, _UA_CLEANUP_PHASE | match_handler,
exc->exception_class, exc, context);
if (code == _URC_INSTALL_CONTEXT)
break;
if (code != _URC_CONTINUE_UNWIND)
return _URC_FATAL_PHASE2_ERROR;
}
/* Don't let us unwind past the handler context. */
if (match_handler)
abort ();
uw_update_context (context, &fs);
}
return code;
}
/* Raise an exception, passing along the given exception object. */
_Unwind_Reason_Code
_Unwind_RaiseException(struct _Unwind_Exception *exc)
{
struct _Unwind_Context this_context, cur_context;
_Unwind_Reason_Code code;
uw_init_context (&this_context);
cur_context = this_context;
/* Phase 1: Search. Unwind the stack, calling the personality routine
with the _UA_SEARCH_PHASE flag set. Do not modify the stack yet. */
while (1)
{
_Unwind_FrameState fs;
code = uw_frame_state_for (&cur_context, &fs);
if (code == _URC_END_OF_STACK)
/* Hit end of stack with no handler found. */
return _URC_END_OF_STACK;
if (code != _URC_NO_REASON)
/* Some error encountered. Ususally the unwinder doesn't
diagnose these and merely crashes. */
return _URC_FATAL_PHASE1_ERROR;
/* Unwind successful. Run the personality routine, if any. */
if (fs.personality)
{
code = (*fs.personality) (1, _UA_SEARCH_PHASE, exc->exception_class,
exc, &cur_context);
if (code == _URC_HANDLER_FOUND)
break;
else if (code != _URC_CONTINUE_UNWIND)
return _URC_FATAL_PHASE1_ERROR;
}
uw_update_context (&cur_context, &fs);
}
/* Indicate to _Unwind_Resume and associated subroutines that this
is not a forced unwind. Further, note where we found a handler. */
exc->private_1 = 0;
exc->private_2 = uw_identify_context (&cur_context);
cur_context = this_context;
code = _Unwind_RaiseException_Phase2 (exc, &cur_context);
if (code != _URC_INSTALL_CONTEXT)
return code;
uw_install_context (&this_context, &cur_context);
}
/* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume. */
static _Unwind_Reason_Code
_Unwind_ForcedUnwind_Phase2(struct _Unwind_Exception *exc,
struct _Unwind_Context *context)
{
_Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) exc->private_1;
void *stop_argument = (void *) exc->private_2;
_Unwind_Reason_Code code, stop_code;
while (1)
{
_Unwind_FrameState fs;
code = uw_frame_state_for (context, &fs);
if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
return _URC_FATAL_PHASE2_ERROR;
/* Unwind successful. */
stop_code = (*stop) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE,
exc->exception_class, exc, context, stop_argument);
if (stop_code != _URC_NO_REASON)
return _URC_FATAL_PHASE2_ERROR;
/* Stop didn't want to do anything. Invoke the personality
handler, if applicable, to run cleanups. */
if (code == _URC_END_OF_STACK)
break;
if (fs.personality)
{
code = (*fs.personality) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE,
exc->exception_class, exc, context);
if (code == _URC_INSTALL_CONTEXT)
break;
if (code != _URC_CONTINUE_UNWIND)
return _URC_FATAL_PHASE2_ERROR;
}
uw_update_context (context, &fs);
}
return code;
}
/* Raise an exception for forced unwinding. */
_Unwind_Reason_Code
_Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
_Unwind_Stop_Fn stop, void * stop_argument)
{
struct _Unwind_Context this_context, cur_context;
_Unwind_Reason_Code code;
uw_init_context (&this_context);
cur_context = this_context;
exc->private_1 = (_Unwind_Ptr) stop;
exc->private_2 = (_Unwind_Ptr) stop_argument;
code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
if (code != _URC_INSTALL_CONTEXT)
return code;
uw_install_context (&this_context, &cur_context);
}
/* Resume propagation of an existing exception. This is used after
e.g. executing cleanup code, and not to implement rethrowing. */
void
_Unwind_Resume (struct _Unwind_Exception *exc)
{
struct _Unwind_Context this_context, cur_context;
_Unwind_Reason_Code code;
uw_init_context (&this_context);
cur_context = this_context;
/* Choose between continuing to process _Unwind_RaiseException
or _Unwind_ForcedUnwind. */
if (exc->private_1 == 0)
code = _Unwind_RaiseException_Phase2 (exc, &cur_context);
else
code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
if (code != _URC_INSTALL_CONTEXT)
abort ();
uw_install_context (&this_context, &cur_context);
}
/* A convenience function that calls the exception_cleanup field. */
void
_Unwind_DeleteException (struct _Unwind_Exception *exc)
{
(*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
}

View File

@ -1,3 +1,29 @@
2001-03-28 Richard Henderson <rth@redhat.com>
IA-64 ABI Exception Handling:
* Makefile.am (GCC_UNWIND_INCLUDE): Rename from EH_COMMON_INCLUDE.
(AM_CXXFLAGS): -fnon-call-exceptions not -fasynchronous-exceptions.
Remove EXCEPTIONSPEC.
* configure.host (libgcj_sjlj): Remove.
* configure.in (EXCEPTIONSPEC): Remove.
(enable-sjlj-exceptions): Detect if not specified.
(GCC_UNWIND_INCLUDE): Rename from EH_COMMON_INCLUDE; change
what header we're looking for.
* libgcj.spec.in (jc1): Remove EXCEPTIONSPEC.
* Makefile.in, configure: Regenerate.
* exception.cc: Don't declare libgcc2 stuff.
(java_eh_info, _Jv_type_matcher, _Jv_exception_info): Remove.
(_Jv_eh_alloc, _Jv_eh_free, _Jv_setup_eh_info): Remove.
(win32_get_restart_frame): Remove.
(struct java_exception_header): New.
(__gcj_exception_class): New.
(get_exception_header_from_ue): New.
(_Jv_Throw): Rewrite for IA-64 ABI unwind routines.
(size_of_encoded_value, read_encoded_value): New.
(read_uleb128, read_sleb128, parse_lsda_header): New.
(get_ttype_entry, __gcj_personality_sj0): New.
* gcj/javaprims.h (_Jv_Sjlj_Throw): Remove.
2001-03-27 Joerg Brunsmann <joerg_brunsmann@yahoo.de>
* javax/naming/InitialContext.java (init): Fix typo.

View File

@ -87,18 +87,15 @@ LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(
JAVAC = $(GCJ_WITH_FLAGS) -C
EH_COMMON_INCLUDE = @EH_COMMON_INCLUDE@
GCC_UNWIND_INCLUDE = @GCC_UNWIND_INCLUDE@
WARNINGS = -W -Wall
## We need _GNU_SOURCE defined for some Linux builds. It doesn't hurt
## to always define it.
## Note that we need -fasynchronous-exceptions because gcc is
## currently broken with respect to exception handling in leaf
## functions.
AM_CXXFLAGS = -fno-rtti -fvtable-thunks -fasynchronous-exceptions \
AM_CXXFLAGS = -fno-rtti -fvtable-thunks -fnon-call-exceptions \
## Some systems don't allow `$' in identifiers by default, so we force it.
-fdollars-in-identifiers \
@LIBGCJ_CXXFLAGS@ @EXCEPTIONSPEC@ @X_CFLAGS@ $(WARNINGS) -D_GNU_SOURCE
@LIBGCJ_CXXFLAGS@ @X_CFLAGS@ $(WARNINGS) -D_GNU_SOURCE
if USING_GCC
AM_CFLAGS = @LIBGCJ_CFLAGS@ $(WARNINGS)
else
@ -112,7 +109,7 @@ LIBFFIINCS = -I$(top_srcdir)/../libffi/include -I$(MULTIBUILDTOP)../libffi/inclu
INCLUDES = -I$(top_srcdir) -Iinclude -I$(top_srcdir)/include \
$(GCINCS) $(THREADINCS) $(INCLTDL) \
$(EH_COMMON_INCLUDE) $(ZINCS) $(LIBFFIINCS)
$(GCC_UNWIND_INCLUDE) $(ZINCS) $(LIBFFIINCS)
## ################################################################

View File

@ -153,12 +153,12 @@ LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(
JAVAC = $(GCJ_WITH_FLAGS) -C
EH_COMMON_INCLUDE = @EH_COMMON_INCLUDE@
GCC_UNWIND_INCLUDE = @GCC_UNWIND_INCLUDE@
WARNINGS = -W -Wall
AM_CXXFLAGS = -fno-rtti -fvtable-thunks -fasynchronous-exceptions \
AM_CXXFLAGS = -fno-rtti -fvtable-thunks -fnon-call-exceptions \
-fdollars-in-identifiers \
@LIBGCJ_CXXFLAGS@ @EXCEPTIONSPEC@ @X_CFLAGS@ $(WARNINGS) -D_GNU_SOURCE
@LIBGCJ_CXXFLAGS@ @X_CFLAGS@ $(WARNINGS) -D_GNU_SOURCE
@USING_GCC_TRUE@AM_CFLAGS = @USING_GCC_TRUE@@LIBGCJ_CFLAGS@ $(WARNINGS)
@USING_GCC_FALSE@AM_CFLAGS = @USING_GCC_FALSE@@LIBGCJ_CFLAGS@
@ -170,7 +170,7 @@ LIBFFIINCS = -I$(top_srcdir)/../libffi/include -I$(MULTIBUILDTOP)../libffi/inclu
INCLUDES = -I$(top_srcdir) -Iinclude -I$(top_srcdir)/include \
$(GCINCS) $(THREADINCS) $(INCLTDL) \
$(EH_COMMON_INCLUDE) $(ZINCS) $(LIBFFIINCS)
$(GCC_UNWIND_INCLUDE) $(ZINCS) $(LIBFFIINCS)
nat_files = $(nat_source_files:.cc=.lo)

776
libjava/configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,6 @@ libgcj_flags=
libgcj_cflags=
libgcj_cxxflags=
libgcj_javaflags=
libgcj_sjlj=
libgcj_interpreter=
case "${target_optspace}:${host}" in
@ -67,18 +66,13 @@ case "${host}" in
alpha*-*)
libgcj_flags="${libgcj_flags} -mieee"
libgcj_interpreter=yes
libgcj_sjlj=yes
;;
sparc-*)
;;
ia64-*)
libgcj_flags="${libgcj_flags} -funwind-tables"
libgcj_sjlj=yes
libgcj_interpreter=yes
;;
*)
libgcj_sjlj=yes
;;
esac
libgcj_cflags="${libgcj_cflags} ${libgcj_flags}"

View File

@ -88,19 +88,51 @@ if test "$libgcj_interpreter" = yes; then
AC_DEFINE(INTERPRETER)
fi
EXCEPTIONSPEC=
dnl See if we should use setjmp/longjmp exceptions
AC_MSG_CHECKING([for exception model to use])
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_ARG_ENABLE(sjlj-exceptions,
[ --enable-sjlj-exceptions use setjmp/longjmp exceptions],
if test "$enable_sjlj_exceptions" = yes; then
# This can be set in configure.host.
libgcj_sjlj=yes
fi)
if test "$libgcj_sjlj" = yes; then
EXCEPTIONSPEC="-fsjlj-exceptions"
AC_DEFINE(SJLJ_EXCEPTIONS)
[ --enable-sjlj-exceptions force use of builtin_setjmp for exceptions],
[:],
[dnl Botheration. Now we've got to detect the exception model.
dnl Link tests against libgcc.a are problematic since -- at least
dnl as of this writing -- we've not been given proper -L bits for
dnl single-tree newlib and libgloss.
dnl
dnl This is what AC_TRY_COMPILE would do if it didn't delete the
dnl conftest files before we got a change to grep them first.
cat > conftest.$ac_ext << EOF
[#]line __oline__ "configure"
struct S { ~S(); };
void bar();
void foo()
{
S s;
bar();
}
EOF
old_CXXFLAGS="$CXXFLAGS"
CXXFLAGS=-S
if AC_TRY_EVAL(ac_compile); then
if grep _Unwind_SjLj_Resume conftest.s >/dev/null 2>&1 ; then
enable_sjlj_exceptions=yes
elif grep _Unwind_Resume conftest.s >/dev/null 2>&1 ; then
enable_sjlj_exceptions=no
fi
fi
CXXFLAGS="$old_CXXFLAGS"
rm -f conftest*])
if test x$enable_sjlj_exceptions = xyes; then
AC_DEFINE(SJLJ_EXCEPTIONS, 1,
[Define if the compiler is configured for setjmp/longjmp exceptions.])
ac_exception_model_name=sjlj
elif test x$enable_sjlj_exceptions = xno; then
ac_exception_model_name="call frame"
else
AC_MSG_ERROR([unable to detect exception model])
fi
AC_LANG_RESTORE
AC_MSG_RESULT($ac_exception_model_name)
AC_MSG_CHECKING([for data_start])
LIBDATASTARTSPEC=
@ -349,16 +381,17 @@ CANADIAN=no
NULL_TARGET=no
NATIVE=yes
# Find eh-common.h and support headers. If we're in the tree with
# Find unwind.h and support headers. If we're in the tree with
# gcc, then look there. Otherwise look in compat-include. If all else
# fails, just hope the user has set things up somehow.
if test -r $srcdir/../gcc/eh-common.h; then
EH_COMMON_INCLUDE='-I$(top_srcdir)/../gcc -I$(top_srcdir)/../include'
echo "probing $srcdir/../gcc/unwind.h"
if test -r $srcdir/../gcc/unwind.h; then
GCC_UNWIND_INCLUDE='-I$(top_srcdir)/../gcc'
else
if test -d $srcdir/../compat-include; then
EH_COMMON_INCLUDE='-I$(top_srcdir)/../compat-include'
GCC_UNWIND_INCLUDE='-I$(top_srcdir)/../compat-include'
else
EH_COMMON_INCLUDE=
GCC_UNWIND_INCLUDE=
fi
fi
@ -389,7 +422,7 @@ if test -n "${with_cross_host}"; then
# directory.
if test "$build" != "$with_cross_host"; then
CANADIAN=yes
EH_COMMON_INCLUDE=
GCC_UNWIND_INCLUDE=
GCJ="${target_alias}-gcj"
else
GCJ=
@ -623,14 +656,13 @@ AC_SUBST(ZLIBS)
AC_SUBST(ZDEPS)
AC_SUBST(ZINCS)
AC_SUBST(DIVIDESPEC)
AC_SUBST(EXCEPTIONSPEC)
AM_CONDITIONAL(CANADIAN, test "$CANADIAN" = yes)
AM_CONDITIONAL(NULL_TARGET, test "$NULL_TARGET" = yes)
AM_CONDITIONAL(NATIVE, test "$NATIVE" = yes || test "$NULL_TARGET" = yes)
AM_CONDITIONAL(USE_LIBDIR, test -z "$with_cross_host")
AM_CONDITIONAL(NEEDS_DATA_START, test "$NEEDS_DATA_START" = yes && test "$NATIVE" = yes)
AC_SUBST(EH_COMMON_INCLUDE)
AC_SUBST(GCC_UNWIND_INCLUDE)
# Determine gcj version number.
changequote(<<,>>)

View File

@ -1,6 +1,6 @@
// Functions for Exception Support for Java.
/* Copyright (C) 1998, 1999 Free Software Foundation
/* Copyright (C) 1998, 1999, 2001 Free Software Foundation
This file is part of libgcj.
@ -18,182 +18,546 @@ details. */
#include <gcj/cni.h>
#include <jvm.h>
// eh-common.h needs gansidecl.h.
#include "gansidecl.h"
#include "eh-common.h"
#include "unwind.h"
// More nastiness: the GC wants to define TRUE and FALSE. We don't
// need the Java definitions (themselves a hack), so we undefine them.
#undef TRUE
#undef FALSE
extern "C"
{
#include <gc_priv.h>
#include <gc_mark.h>
#include <include/gc_gcj.h>
};
struct alignment_test_struct
{
char space;
char end[0] __attribute__((aligned));
};
struct java_exception_header
{
/* Cache handler details between Phase 1 and Phase 2. */
_Unwind_Ptr landingPad;
int handlerSwitchValue;
/* The object being thrown. Compiled code expects this to be immediately
before the generic exception header. Which is complicated by the fact
that _Unwind_Exception is ((aligned)). */
char pad[sizeof(jthrowable) < sizeof(alignment_test_struct)
? sizeof(alignment_test_struct) - sizeof(jthrowable) : 0]
__attribute__((aligned));
typedef struct {
__eh_info eh_info;
jthrowable value;
} java_eh_info;
/* The generic exception header. */
_Unwind_Exception unwindHeader;
};
// This is the exception class we report -- "GNUCJAVA".
const _Unwind_Exception_Class __gcj_exception_class
= ((((((((_Unwind_Exception_Class) 'G'
<< 8 | (_Unwind_Exception_Class) 'N')
<< 8 | (_Unwind_Exception_Class) 'U')
<< 8 | (_Unwind_Exception_Class) 'C')
<< 8 | (_Unwind_Exception_Class) 'J')
<< 8 | (_Unwind_Exception_Class) 'A')
<< 8 | (_Unwind_Exception_Class) 'V')
<< 8 | (_Unwind_Exception_Class) 'A');
/* Language-specific EH info pointer, throw routine, and language/version
info routines. All defined in libgcc2. */
extern "C" java_eh_info **__get_eh_info ();
extern "C" void __throw () __attribute__ ((__noreturn__));
extern "C" void __sjthrow () __attribute__ ((__noreturn__));
extern "C" short __get_eh_table_version (void *table);
extern "C" short __get_eh_table_language (void *table);
extern "C" void *__get_eh_context ();
extern "C" void *
_Jv_type_matcher (java_eh_info *info, void* match_info,
void *exception_table)
{
#ifndef SJLJ_EXCEPTIONS
/* No exception table implies the old style mechanism, so don't check. */
if (exception_table != NULL
&& __get_eh_table_language (exception_table) != EH_LANG_Java)
return NULL;
#endif
/* we don't worry about version info yet, there is only one version! */
if (match_info != NULL)
{
// The match_info is either a (java::lang::Class*) or
// match_info is one more than a (Utf8Const*).
if (sizeof(void*) != sizeof(size_t))
abort();
size_t mi = (size_t) match_info;
if ((mi & 1) != 0)
match_info = _Jv_FindClass ((Utf8Const*) (mi - 1), NULL);
if (! _Jv_IsInstanceOf (info->value, (jclass) match_info))
return NULL;
}
return info->value;
}
/* Compiler hook to return a pointer to java exception object. The value
is cleared, so if the exception needs to be rethrown, it should be set
again */
extern "C" void *
_Jv_exception_info (void)
{
java_eh_info *info = *(__get_eh_info ());
void *ptr;
if (info == NULL)
abort ();
ptr = info->value;
/* clear the value so another throw is an error */
info->value = NULL;
return ptr;
}
/* Allocate an exception info structure for java. Called the first time
an exception is thrown. */
extern "C" void
_Jv_eh_alloc ()
{
/* FIXME: we should use _Jv_AllocBytes here. However, libgcc2
apparently can sometimes free() this value itself. */
java_eh_info *p = (java_eh_info *) malloc (sizeof (java_eh_info));
if (p == 0)
abort ();
p->value = 0;
java_eh_info ** info_ptr = __get_eh_info ();
/* There should NOT be an exception info pointer already. */
if (*info_ptr != NULL)
abort ();
*info_ptr = p;
}
/* Deallocate the current exception info structure. Called at shutdown time. */
extern "C" void
_Jv_eh_free ()
{
java_eh_info ** info_ptr = __get_eh_info ();
if (*info_ptr == NULL)
abort ();
/* FIXME: ideally we should just let the GC handle this. */
free (*info_ptr);
*info_ptr = NULL;
}
/* Initialize an __eh_info structure with this libraries matching info. */
extern "C" void
_Jv_setup_eh_info (__eh_info *)
static inline java_exception_header *
get_exception_header_from_ue (_Unwind_Exception *exc)
{
return reinterpret_cast<java_exception_header *>(exc + 1) - 1;
}
/* Perform a throw, Java style. Throw will unwind through this call,
so there better not be any handlers or exception thrown here. */
#ifdef SJLJ_EXCEPTIONS
#define _Jv_Throw _Jv_Sjlj_Throw
#endif
extern "C" void
_Jv_Throw (jthrowable value)
{
/* FIXME: Use the proper API to the collector. */
java_exception_header *xh
= static_cast<java_exception_header *>(GC_malloc (sizeof (*xh)));
if (value == NULL)
value = new java::lang::NullPointerException;
java_eh_info *ehinfo = *(__get_eh_info ());
if (ehinfo == NULL)
{
_Jv_eh_alloc ();
ehinfo = *(__get_eh_info ());
}
ehinfo->eh_info.match_function = (__eh_matcher) _Jv_type_matcher;
ehinfo->eh_info.language = EH_LANG_Java;
ehinfo->eh_info.version = 1;
ehinfo->value = value;
value = new java::lang::NullPointerException ();
xh->value = value;
/* We're happy with setjmp/longjmp exceptions or region-based
exception handlers: entry points are provided here for both. */
xh->unwindHeader.exception_class = __gcj_exception_class;
xh->unwindHeader.exception_cleanup = NULL;
/* We're happy with setjmp/longjmp exceptions or region-based
exception handlers: entry points are provided here for both. */
_Unwind_Reason_Code code;
#ifdef SJLJ_EXCEPTIONS
__sjthrow ();
code = _Unwind_SjLj_RaiseException (&xh->unwindHeader);
#else
__throw ();
code = _Unwind_RaiseException (&xh->unwindHeader);
#endif
/* FIXME: If code == _URC_END_OF_STACK, then we reached top of
stack without finding a handler for the exception. I seem to
recall that Java has specific rules to handle this.
If code is something else, we encountered some sort of heinous
lossage, from which we could not recover. As is the way of such
things we'll almost certainly have crashed before now, rather
than actually being able to diagnose the problem. */
abort ();
}
#ifdef USE_WIN32_SIGNALLING
// ??? These ought to go somewhere else dwarf2 or dwarf2eh related.
// This is a mangled version of _Jv_Throw and __sjthrow except
// rather than calling longjmp, it returns a pointer to the jmp buffer
// Pointer encodings.
#define DW_EH_PE_absptr 0x00
#define DW_EH_PE_omit 0xff
extern "C" int *
win32_get_restart_frame (void *value)
#define DW_EH_PE_uleb128 0x01
#define DW_EH_PE_udata2 0x02
#define DW_EH_PE_udata4 0x03
#define DW_EH_PE_udata8 0x04
#define DW_EH_PE_sleb128 0x09
#define DW_EH_PE_sdata2 0x0A
#define DW_EH_PE_sdata4 0x0B
#define DW_EH_PE_sdata8 0x0C
#define DW_EH_PE_signed 0x08
#define DW_EH_PE_pcrel 0x10
#define DW_EH_PE_textrel 0x20
#define DW_EH_PE_datarel 0x30
#define DW_EH_PE_funcrel 0x40
static unsigned int
size_of_encoded_value (unsigned char encoding)
{
struct eh_context *eh = (struct eh_context *)__get_eh_context ();
void ***dhc = &eh->dynamic_handler_chain;
java_eh_info *ehinfo = *(__get_eh_info ());
if (ehinfo == NULL)
switch (encoding & 0x07)
{
_Jv_eh_alloc ();
ehinfo = *(__get_eh_info ());
case DW_EH_PE_absptr:
return sizeof (void *);
case DW_EH_PE_udata2:
return 2;
case DW_EH_PE_udata4:
return 4;
case DW_EH_PE_udata8:
return 8;
}
ehinfo->eh_info.match_function = (__eh_matcher) _Jv_type_matcher;
ehinfo->eh_info.language = EH_LANG_Java;
ehinfo->eh_info.version = 1;
ehinfo->value = value;
// FIXME: Run clean ups?
int *jmpbuf = (int*)&(*dhc)[2];
*dhc = (void**)(*dhc)[0];
return jmpbuf;
abort ();
}
#endif /* USE_WIN32_SIGNALLING */
static const unsigned char *
read_encoded_value (_Unwind_Context *context, unsigned char encoding,
const unsigned char *p, _Unwind_Ptr *val)
{
union unaligned
{
void *ptr;
unsigned u2 __attribute__ ((mode (HI)));
unsigned u4 __attribute__ ((mode (SI)));
unsigned u8 __attribute__ ((mode (DI)));
signed s2 __attribute__ ((mode (HI)));
signed s4 __attribute__ ((mode (SI)));
signed s8 __attribute__ ((mode (DI)));
} __attribute__((__packed__));
union unaligned *u = (union unaligned *) p;
_Unwind_Ptr result;
switch (encoding & 0x0f)
{
case DW_EH_PE_absptr:
result = (_Unwind_Ptr) u->ptr;
p += sizeof (void *);
break;
case DW_EH_PE_uleb128:
{
unsigned int shift = 0;
unsigned char byte;
result = 0;
do
{
byte = *p++;
result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
shift += 7;
}
while (byte & 0x80);
}
break;
case DW_EH_PE_sleb128:
{
unsigned int shift = 0;
unsigned char byte;
result = 0;
do
{
byte = *p++;
result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
shift += 7;
}
while (byte & 0x80);
if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
result |= -(1L << shift);
}
break;
case DW_EH_PE_udata2:
result = u->u2;
p += 2;
break;
case DW_EH_PE_udata4:
result = u->u4;
p += 4;
break;
case DW_EH_PE_udata8:
result = u->u8;
p += 8;
break;
case DW_EH_PE_sdata2:
result = u->s2;
p += 2;
break;
case DW_EH_PE_sdata4:
result = u->s4;
p += 4;
break;
case DW_EH_PE_sdata8:
result = u->s8;
p += 8;
break;
default:
abort ();
}
if (result != 0)
switch (encoding & 0xf0)
{
case DW_EH_PE_absptr:
break;
case DW_EH_PE_pcrel:
// Define as relative to the beginning of the pointer.
result += (_Unwind_Ptr) u;
break;
case DW_EH_PE_textrel:
case DW_EH_PE_datarel:
// FIXME.
abort ();
case DW_EH_PE_funcrel:
result += _Unwind_GetRegionStart (context);
break;
default:
abort ();
}
*val = result;
return p;
}
static inline const unsigned char *
read_uleb128 (const unsigned char *p, _Unwind_Ptr *val)
{
return read_encoded_value (0, DW_EH_PE_uleb128, p, val);
}
static inline const unsigned char *
read_sleb128 (const unsigned char *p, _Unwind_Ptr *val)
{
return read_encoded_value (0, DW_EH_PE_sleb128, p, val);
}
struct lsda_header_info
{
_Unwind_Ptr Start;
_Unwind_Ptr LPStart;
const unsigned char *TType;
const unsigned char *action_table;
unsigned char ttype_encoding;
unsigned char call_site_encoding;
};
static const unsigned char *
parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
lsda_header_info *info)
{
_Unwind_Ptr tmp;
unsigned char lpstart_encoding;
info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
// Find @LPStart, the base to which landing pad offsets are relative.
lpstart_encoding = *p++;
if (lpstart_encoding != DW_EH_PE_omit)
p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
else
info->LPStart = info->Start;
// Find @TType, the base of the handler and exception spec type data.
info->ttype_encoding = *p++;
if (info->ttype_encoding != DW_EH_PE_omit)
{
p = read_uleb128 (p, &tmp);
info->TType = p + tmp;
}
else
info->TType = 0;
// The encoding and length of the call-site table; the action table
// immediately follows.
info->call_site_encoding = *p++;
p = read_uleb128 (p, &tmp);
info->action_table = p + tmp;
return p;
}
static jclass
get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
{
_Unwind_Ptr ptr;
i *= size_of_encoded_value (info->ttype_encoding);
read_encoded_value (context, info->ttype_encoding, info->TType - i, &ptr);
return reinterpret_cast<jclass>(ptr);
}
// Using a different personality function name causes link failures
// when trying to mix code using different exception handling models.
#ifdef SJLJ_EXCEPTIONS
#define PERSONALITY_FUNCTION __gcj_personality_sj0
#define __builtin_eh_return_data_regno(x) x
#else
#define PERSONALITY_FUNCTION __gcj_personality_v0
#endif
extern "C" _Unwind_Reason_Code
PERSONALITY_FUNCTION (int version,
_Unwind_Action actions,
_Unwind_Exception_Class exception_class,
struct _Unwind_Exception *ue_header,
struct _Unwind_Context *context)
{
java_exception_header *xh = get_exception_header_from_ue (ue_header);
lsda_header_info info;
const unsigned char *language_specific_data;
const unsigned char *action_record;
const unsigned char *p;
_Unwind_Ptr landing_pad, ip;
int handler_switch_value;
bool saw_cleanup;
bool saw_handler;
// Interface version check.
if (version != 1)
return _URC_FATAL_PHASE1_ERROR;
// Shortcut for phase 2 found handler for domestic exception.
if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
&& exception_class == __gcj_exception_class)
{
handler_switch_value = xh->handlerSwitchValue;
landing_pad = xh->landingPad;
goto install_context;
}
// FIXME: In Phase 1, record _Unwind_GetIP in xh->obj as a part of
// the stack trace for this exception. This will only collect Java
// frames, but perhaps that is acceptable.
// FIXME2: _Unwind_GetIP is nonsensical for SJLJ, being a call-site
// index instead of a PC value. We could perhaps arrange for
// _Unwind_GetRegionStart to return context->fc->jbuf[1], which
// is the address of the handler label for __builtin_longjmp, but
// there is no solution for DONT_USE_BUILTIN_SETJMP.
language_specific_data = (const unsigned char *)
_Unwind_GetLanguageSpecificData (context);
// If no LSDA, then there are no handlers or cleanups.
if (! language_specific_data)
return _URC_CONTINUE_UNWIND;
// Parse the LSDA header.
p = parse_lsda_header (context, language_specific_data, &info);
ip = _Unwind_GetIP (context) - 1;
landing_pad = 0;
action_record = 0;
handler_switch_value = 0;
#ifdef SJLJ_EXCEPTIONS
// The given "IP" is an index into the call-site table, with two
// exceptions -- -1 means no-action, and 0 means terminate. But
// since we're using uleb128 values, we've not got random access
// to the array.
if ((int) ip <= 0)
return _URC_CONTINUE_UNWIND;
else
{
_Unwind_Ptr cs_lp, cs_action;
do
{
p = read_uleb128 (p, &cs_lp);
p = read_uleb128 (p, &cs_action);
}
while (--ip);
// Can never have null landing pad for sjlj -- that would have
// been indicated by a -1 call site index.
landing_pad = cs_lp + 1;
if (cs_action)
action_record = info.action_table + cs_action - 1;
goto found_something;
}
#else
// Search the call-site table for the action associated with this IP.
while (p < info.action_table)
{
_Unwind_Ptr cs_start, cs_len, cs_lp, cs_action;
// Note that all call-site encodings are "absolute" displacements.
p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
p = read_uleb128 (p, &cs_action);
// The table is sorted, so if we've passed the ip, stop.
if (ip < info.Start + cs_start)
p = info.action_table;
else if (ip < info.Start + cs_start + cs_len)
{
if (cs_lp)
landing_pad = info.LPStart + cs_lp;
if (cs_action)
action_record = info.action_table + cs_action - 1;
goto found_something;
}
}
#endif // SJLJ_EXCEPTIONS
// If ip is not present in the table, C++ would call terminate.
// ??? It is perhaps better to tweek the LSDA so that no-action
// is mapped to no-entry for Java.
return _URC_CONTINUE_UNWIND;
found_something:
saw_cleanup = false;
saw_handler = false;
if (landing_pad == 0)
{
// If ip is present, and has a null landing pad, there are
// no cleanups or handlers to be run.
}
else if (action_record == 0)
{
// If ip is present, has a non-null landing pad, and a null
// action table offset, then there are only cleanups present.
// Cleanups use a zero switch value, as set above.
saw_cleanup = true;
}
else
{
// Otherwise we have a catch handler.
signed long ar_filter, ar_disp;
while (1)
{
_Unwind_Ptr tmp;
p = action_record;
p = read_sleb128 (p, &tmp); ar_filter = tmp;
read_sleb128 (p, &tmp); ar_disp = tmp;
if (ar_filter == 0)
{
// Zero filter values are cleanups.
saw_cleanup = true;
}
// During forced unwinding, we only run cleanups. With a
// foreign exception class, we have no class info to match.
else if ((actions & _UA_FORCE_UNWIND)
|| exception_class != __gcj_exception_class)
;
else if (ar_filter > 0)
{
// Positive filter values are handlers.
jclass catch_type = get_ttype_entry (context, &info, ar_filter);
// The catch_type is either a (java::lang::Class*) or
// is one more than a (Utf8Const*).
if ((size_t)catch_type & 1)
catch_type = _Jv_FindClass ((Utf8Const*)catch_type - 1, NULL);
if (_Jv_IsInstanceOf (xh->value, catch_type))
{
handler_switch_value = ar_filter;
saw_handler = true;
break;
}
}
else
{
// Negative filter values are exception specifications,
// which Java does not use.
// ??? Perhaps better to make them an index into a table
// of null-terminated strings instead of playing games
// with Utf8Const+1 as above.
abort ();
}
if (ar_disp == 0)
break;
action_record = p + ar_disp;
}
}
if (! saw_handler && ! saw_cleanup)
return _URC_CONTINUE_UNWIND;
if (actions & _UA_SEARCH_PHASE)
{
if (! saw_handler)
return _URC_CONTINUE_UNWIND;
// For domestic exceptions, we cache data from phase 1 for phase 2.
if (exception_class == __gcj_exception_class)
{
xh->handlerSwitchValue = handler_switch_value;
xh->landingPad = landing_pad;
}
return _URC_HANDLER_FOUND;
}
install_context:
_Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
(_Unwind_Ptr) &xh->unwindHeader);
_Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
handler_switch_value);
_Unwind_SetIP (context, landing_pad);
return _URC_INSTALL_CONTEXT;
}

View File

@ -369,7 +369,6 @@ extern "C" jsize _Jv_GetStringUTFLength (jstring);
extern "C" jsize _Jv_GetStringUTFRegion (jstring, jsize, jsize, char *);
extern "C" void _Jv_Throw (jthrowable) __attribute__ ((__noreturn__));
extern "C" void _Jv_Sjlj_Throw (jthrowable) __attribute__ ((__noreturn__));
extern "C" void* _Jv_Malloc (jsize) __attribute__((__malloc__));
extern "C" void* _Jv_Realloc (void *, jsize);
extern "C" void _Jv_Free (void*);

View File

@ -6,7 +6,7 @@
%rename lib liborig
*lib: -lgcj -lm @GCSPEC@ @THREADSPEC@ @ZLIBSPEC@ @SYSTEMSPEC@ %(libgcc) %(liborig)
*jc1: @DIVIDESPEC@ @EXCEPTIONSPEC@ @JC1GCSPEC@ -fasynchronous-exceptions
*jc1: @DIVIDESPEC@ @JC1GCSPEC@
#
# On some systems we force in a data_start symbol so that the GC will work

View File

@ -1,3 +1,23 @@
2001-03-28 Richard Henderson <rth@redhat.com>
IA-64 ABI Exception Handling:
* acinclude.m4 (GLIBCPP_ENABLE_SJLJ_EXCEPTIONS): New.
* configure.in: Use it.
* Makefile.in, aclocal.m4, config.h.in, configure: Regenerate.
* libsupc++/Makefile.am (sources): Update files list.
* libsupc++/Makefile.in: Regenerate.
* libsupc++/eh_alloc.cc, libsupc++/eh_aux_runtime.cc: New files.
* libsupc++/eh_catch.cc, libsupc++/eh_exception.cc: New files.
* libsupc++/eh_globals.cc, libsupc++/eh_personality.cc: New files.
* libsupc++/eh_terminate.cc, libsupc++/eh_throw.cc: New files.
* libsupc++/exception_support.cc: Remove.
* libsupc++/exception_support.h: Remove.
* libsupc++/pure.cc: Use std::terminate.
* libsupc++/tinfo2.cc (__throw_type_match_rtti_2): Remove.
(__is_pointer): Remove.
* libsupc++/unwind-cxx.h: New file.
* libsupc++/vec.cc (uncatch_exception): Update for new abi.
2001-03-27 Alexandre Oliva <aoliva@redhat.com>
* libsupc++/Makefile.am (CXXLINK): Use CXX again, and choose

View File

@ -134,48 +134,7 @@ MULTICLEAN = true
# Work around what appears to be a GNU make bug handling MAKEFLAGS
# values defined in terms of make variables, as is the case for CC and
# friends when we are called from the top level Makefile.
AM_MAKEFLAGS = \
"AR_FLAGS=$(AR_FLAGS)" \
"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
"CC_FOR_TARGET=$(CC_FOR_TARGET)" \
"CFLAGS=$(CFLAGS)" \
"CXXFLAGS=$(CXXFLAGS)" \
"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
"INSTALL=$(INSTALL)" \
"INSTALL_DATA=$(INSTALL_DATA)" \
"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
"LDFLAGS=$(LDFLAGS)" \
"LIBCFLAGS=$(LIBCFLAGS)" \
"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
"MAKE=$(MAKE)" \
"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
"PICFLAG=$(PICFLAG)" \
"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
"SHELL=$(SHELL)" \
"EXPECT=$(EXPECT)" \
"RUNTEST=$(RUNTEST)" \
"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
"exec_prefix=$(exec_prefix)" \
"infodir=$(infodir)" \
"libdir=$(libdir)" \
"includedir=$(includedir)" \
"prefix=$(prefix)" \
"tooldir=$(tooldir)" \
"AR=$(AR)" \
"AS=$(AS)" \
"CC=$(CC)" \
"CXX=$(CXX)" \
"LD=$(LD)" \
"LIBCFLAGS=$(LIBCFLAGS)" \
"PICFLAG=$(PICFLAG)" \
"RANLIB=$(RANLIB)" \
"NM=$(NM)" \
"NM_FOR_BUILD=$(NM_FOR_BUILD)" \
"NM_FOR_TARGET=$(NM_FOR_TARGET)" \
"DESTDIR=$(DESTDIR)" \
"WERROR=$(WERROR)"
AM_MAKEFLAGS = "AR_FLAGS=$(AR_FLAGS)" "CC_FOR_BUILD=$(CC_FOR_BUILD)" "CC_FOR_TARGET=$(CC_FOR_TARGET)" "CFLAGS=$(CFLAGS)" "CXXFLAGS=$(CXXFLAGS)" "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" "INSTALL=$(INSTALL)" "INSTALL_DATA=$(INSTALL_DATA)" "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" "LDFLAGS=$(LDFLAGS)" "LIBCFLAGS=$(LIBCFLAGS)" "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" "MAKE=$(MAKE)" "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" "PICFLAG=$(PICFLAG)" "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" "SHELL=$(SHELL)" "EXPECT=$(EXPECT)" "RUNTEST=$(RUNTEST)" "RUNTESTFLAGS=$(RUNTESTFLAGS)" "exec_prefix=$(exec_prefix)" "infodir=$(infodir)" "libdir=$(libdir)" "includedir=$(includedir)" "prefix=$(prefix)" "tooldir=$(tooldir)" "AR=$(AR)" "AS=$(AS)" "CC=$(CC)" "CXX=$(CXX)" "LD=$(LD)" "LIBCFLAGS=$(LIBCFLAGS)" "PICFLAG=$(PICFLAG)" "RANLIB=$(RANLIB)" "NM=$(NM)" "NM_FOR_BUILD=$(NM_FOR_BUILD)" "NM_FOR_TARGET=$(NM_FOR_TARGET)" "DESTDIR=$(DESTDIR)" "WERROR=$(WERROR)"
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
CONFIG_HEADER = config.h
@ -353,7 +312,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
if test -f $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \

View File

@ -1257,6 +1257,66 @@ AC_DEFUN(GLIBCPP_ENABLE_THREADS, [
])
dnl
dnl Check for exception handling support. If an explicit enable/disable
dnl sjlj exceptions is given, we don't have to detect. Otherwise the
dnl target may or may not support call frame exceptions.
dnl
dnl GLIBCPP_ENABLE_SJLJ_EXCEPTIONS
dnl --enable-sjlj-exceptions forces the use of builtin setjmp.
dnl --disable-sjlj-exceptions forces the use of call frame unwinding.
dnl
dnl Define _GLIBCPP_SJLJ_EXCEPTIONS if the compiler is configured for it.
dnl
AC_DEFUN(GLIBCPP_ENABLE_SJLJ_EXCEPTIONS, [
AC_MSG_CHECKING([for exception model to use])
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_ARG_ENABLE(sjlj-exceptions,
[ --enable-sjlj-exceptions force use of builtin_setjmp for exceptions],
[:],
[dnl Botheration. Now we've got to detect the exception model.
dnl Link tests against libgcc.a are problematic since -- at least
dnl as of this writing -- we've not been given proper -L bits for
dnl single-tree newlib and libgloss.
dnl
dnl This is what AC_TRY_COMPILE would do if it didn't delete the
dnl conftest files before we got a change to grep them first.
cat > conftest.$ac_ext << EOF
[#]line __oline__ "configure"
struct S { ~S(); };
void bar();
void foo()
{
S s;
bar();
}
EOF
old_CXXFLAGS="$CXXFLAGS"
CXXFLAGS=-S
if AC_TRY_EVAL(ac_compile); then
if grep _Unwind_SjLj_Resume conftest.s >/dev/null 2>&1 ; then
enable_sjlj_exceptions=yes
elif grep _Unwind_Resume conftest.s >/dev/null 2>&1 ; then
enable_sjlj_exceptions=no
fi
fi
CXXFLAGS="$old_CXXFLAGS"
rm -f conftest*])
if test x$enable_sjlj_exceptions = xyes; then
AC_DEFINE(_GLIBCPP_SJLJ_EXCEPTIONS, 1,
[Define if the compiler is configured for setjmp/longjmp exceptions.])
ac_exception_model_name=sjlj
elif test x$enable_sjlj_exceptions = xno; then
ac_exception_model_name="call frame"
else
AC_MSG_ERROR([unable to detect exception model])
fi
AC_LANG_RESTORE
AC_MSG_RESULT($ac_exception_model_name)
])
dnl
dnl Check for template specializations for the 'long long' type extension.
dnl

View File

@ -1269,6 +1269,66 @@ AC_DEFUN(GLIBCPP_ENABLE_THREADS, [
])
dnl
dnl Check for exception handling support. If an explicit enable/disable
dnl sjlj exceptions is given, we don't have to detect. Otherwise the
dnl target may or may not support call frame exceptions.
dnl
dnl GLIBCPP_ENABLE_SJLJ_EXCEPTIONS
dnl --enable-sjlj-exceptions forces the use of builtin setjmp.
dnl --disable-sjlj-exceptions forces the use of call frame unwinding.
dnl
dnl Define _GLIBCPP_SJLJ_EXCEPTIONS if the compiler is configured for it.
dnl
AC_DEFUN(GLIBCPP_ENABLE_SJLJ_EXCEPTIONS, [
AC_MSG_CHECKING([for exception model to use])
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_ARG_ENABLE(sjlj-exceptions,
[ --enable-sjlj-exceptions force use of builtin_setjmp for exceptions],
[:],
[dnl Botheration. Now we've got to detect the exception model.
dnl Link tests against libgcc.a are problematic since -- at least
dnl as of this writing -- we've not been given proper -L bits for
dnl single-tree newlib and libgloss.
dnl
dnl This is what AC_TRY_COMPILE would do if it didn't delete the
dnl conftest files before we got a change to grep them first.
cat > conftest.$ac_ext << EOF
[#]line __oline__ "configure"
struct S { ~S(); };
void bar();
void foo()
{
S s;
bar();
}
EOF
old_CXXFLAGS="$CXXFLAGS"
CXXFLAGS=-S
if AC_TRY_EVAL(ac_compile); then
if grep _Unwind_SjLj_Resume conftest.s >/dev/null 2>&1 ; then
enable_sjlj_exceptions=yes
elif grep _Unwind_Resume conftest.s >/dev/null 2>&1 ; then
enable_sjlj_exceptions=no
fi
fi
CXXFLAGS="$old_CXXFLAGS"
rm -f conftest*])
if test x$enable_sjlj_exceptions = xyes; then
AC_DEFINE(_GLIBCPP_SJLJ_EXCEPTIONS, 1,
[Define if the compiler is configured for setjmp/longjmp exceptions.])
ac_exception_model_name=sjlj
elif test x$enable_sjlj_exceptions = xno; then
ac_exception_model_name="call frame"
else
AC_MSG_ERROR([unable to detect exception model])
fi
AC_LANG_RESTORE
AC_MSG_RESULT($ac_exception_model_name)
])
dnl
dnl Check for template specializations for the 'long long' type extension.
dnl

View File

@ -546,6 +546,9 @@
/* Version number of package */
#undef VERSION
/* Define if the compiler is configured for setjmp/longjmp exceptions. */
#undef _GLIBCPP_SJLJ_EXCEPTIONS
/* Define if sigsetjmp is available. */
#undef HAVE_SIGSETJMP

1674
libstdc++-v3/configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -68,6 +68,7 @@ GLIBCPP_ENABLE_LONG_LONG([no])
GLIBCPP_ENABLE_CHEADERS([c_std])
GLIBCPP_ENABLE_THREADS
GLIBCPP_ENABLE_CXX_FLAGS([none])
GLIBCPP_ENABLE_SJLJ_EXCEPTIONS
if test -n "$with_cross_host"; then

View File

@ -110,7 +110,7 @@ toplevel_srcdir = @toplevel_srcdir@
AUTOMAKE_OPTIONS = 1.3 cygnus
mkinstalldirs = $(SHELL) $(toplevel_srcdir)/mkinstalldirs
@GLIBCPP_BUILD_LIBIO_TRUE@noinst_LTLIBRARIES = @GLIBCPP_BUILD_LIBIO_TRUE@libio.la
@GLIBCPP_BUILD_LIBIO_TRUE@noinst_LTLIBRARIES = libio.la
@GLIBCPP_BUILD_LIBIO_FALSE@noinst_LTLIBRARIES =
# Use common includes from acinclude.m4/GLIBCPP_EXPORT_INCLUDES
@ -122,21 +122,14 @@ LIBSUPCXX_INCLUDES = @LIBSUPCXX_INCLUDES@
LIBIO_INCLUDES = @LIBIO_INCLUDES@
CSHADOW_INCLUDES = @CSHADOW_INCLUDES@
INCLUDES = \
-nostdinc++ \
-I$(top_builddir)/include -I$(GLIBCPP_INCLUDE_DIR) \
$(LIBIO_INCLUDES) $(TOPLEVEL_INCLUDES)
INCLUDES = -nostdinc++ -I$(top_builddir)/include -I$(GLIBCPP_INCLUDE_DIR) $(LIBIO_INCLUDES) $(TOPLEVEL_INCLUDES)
libio_headers = \
libio.h libioP.h iolibio.h
libio_headers = libio.h libioP.h iolibio.h
@GLIBCPP_NEED_LIBIO_TRUE@LIBIO_SRCS = @GLIBCPP_NEED_LIBIO_TRUE@\
@GLIBCPP_NEED_LIBIO_TRUE@ filedoalloc.c genops.c fileops.c stdfiles.c c_codecvt.c \
@GLIBCPP_NEED_LIBIO_TRUE@ iofclose.c iofopen.c
@GLIBCPP_NEED_LIBIO_TRUE@LIBIO_SRCS = filedoalloc.c genops.c fileops.c stdfiles.c c_codecvt.c iofclose.c iofopen.c
@GLIBCPP_NEED_LIBIO_FALSE@LIBIO_SRCS =
@GLIBCPP_NEED_WLIBIO_TRUE@LIBIO_WSRCS = @GLIBCPP_NEED_WLIBIO_TRUE@\
@GLIBCPP_NEED_WLIBIO_TRUE@ wfiledoalloc.c wfileops.c wgenops.c iofwide.c
@GLIBCPP_NEED_WLIBIO_TRUE@LIBIO_WSRCS = wfiledoalloc.c wfileops.c wgenops.c iofwide.c
@GLIBCPP_NEED_WLIBIO_FALSE@LIBIO_WSRCS =
EXTRA_DIST = iostreamP.h
@ -299,7 +292,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
if test -f $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \

View File

@ -113,24 +113,18 @@ mkinstalldirs = $(SHELL) $(toplevel_srcdir)/mkinstalldirs
noinst_LTLIBRARIES = libmath.la
EXTRA_LONG_DOUBLE_yes = \
hypotl.c signbitl.c
EXTRA_LONG_DOUBLE_yes = hypotl.c signbitl.c
EXTRA_DIST = \
hypot.c hypotf.c atan2f.c expf.c \
$(EXTRA_LONG_DOUBLE_yes)
EXTRA_DIST = hypot.c hypotf.c atan2f.c expf.c $(EXTRA_LONG_DOUBLE_yes)
libmath_la_LIBADD = \
@LIBMATHOBJS@ \
$(EXTRA_LONG_DOUBLE_$(USE_COMPLEX_LONG_DOUBLE))
libmath_la_LIBADD = @LIBMATHOBJS@ $(EXTRA_LONG_DOUBLE_$(USE_COMPLEX_LONG_DOUBLE))
libmath_la_DEPENDENCIES = $(libmath_la_LIBADD)
libmath_la_SOURCES = \
signbit.c signbitf.c
libmath_la_SOURCES = signbit.c signbitf.c
LINK = $(LIBTOOL) --mode=link "$(CCLD)" $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
@ -144,9 +138,7 @@ LIBSUPCXX_INCLUDES = @LIBSUPCXX_INCLUDES@
LIBIO_INCLUDES = @LIBIO_INCLUDES@
CSHADOW_INCLUDES = @CSHADOW_INCLUDES@
INCLUDES = \
-I$(GLIBCPP_INCLUDE_DIR) -I$(top_builddir)/include \
$(TOPLEVEL_INCLUDES)
INCLUDES = -I$(GLIBCPP_INCLUDE_DIR) -I$(top_builddir)/include $(TOPLEVEL_INCLUDES)
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
@ -277,7 +269,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
if test -f $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \

View File

@ -75,7 +75,14 @@ sources = \
del_opnt.cc \
del_opv.cc \
del_opvnt.cc \
exception_support.cc \
eh_alloc.cc \
eh_aux_runtime.cc \
eh_catch.cc \
eh_exception.cc \
eh_globals.cc \
eh_personality.cc \
eh_terminate.cc \
eh_throw.cc \
new_handler.cc \
new_op.cc \
new_opnt.cc \

View File

@ -127,13 +127,11 @@ OPTIMIZE_CXXFLAGS = @OPTIMIZE_CXXFLAGS@
# These bits are all figured out from configure. Look in acinclude.m4
# or configure.in to see how they are set. See GLIBCPP_EXPORT_FLAGS
# NB: DEBUGFLAGS have to be at the end so that -O2 can be overridden.
CONFIG_CXXFLAGS = \
@EXTRA_CXX_FLAGS@ @SECTION_FLAGS@ @CSHADOW_FLAGS@ @DEBUG_FLAGS@
CONFIG_CXXFLAGS = @EXTRA_CXX_FLAGS@ @SECTION_FLAGS@ @CSHADOW_FLAGS@ @DEBUG_FLAGS@
# Warning flags to use.
WARN_CXXFLAGS = \
@WARN_FLAGS@ $(WERROR) -fdiagnostics-show-location=once
WARN_CXXFLAGS = @WARN_FLAGS@ $(WERROR) -fdiagnostics-show-location=once
# Use common includes from acinclude.m4/GLIBCPP_EXPORT_INCLUDES
@ -145,31 +143,13 @@ LIBSUPCXX_INCLUDES = @LIBSUPCXX_INCLUDES@
LIBIO_INCLUDES = @LIBIO_INCLUDES@
TOPLEVEL_INCLUDES = @TOPLEVEL_INCLUDES@
INCLUDES = \
-I$(toplevel_srcdir)/gcc -I$(toplevel_srcdir)/include \
-I$(GLIBCPP_INCLUDE_DIR) $(CSTD_INCLUDES) -I$(top_builddir)/include \
$(LIBSUPCXX_INCLUDES)
INCLUDES = -I$(toplevel_srcdir)/gcc -I$(toplevel_srcdir)/include -I$(GLIBCPP_INCLUDE_DIR) $(CSTD_INCLUDES) -I$(top_builddir)/include $(LIBSUPCXX_INCLUDES)
headers = \
exception new typeinfo cxxabi.h exception_defines.h
headers = exception new typeinfo cxxabi.h exception_defines.h
sources = \
del_op.cc \
del_opnt.cc \
del_opv.cc \
del_opvnt.cc \
exception_support.cc \
new_handler.cc \
new_op.cc \
new_opnt.cc \
new_opv.cc \
new_opvnt.cc \
pure.cc \
tinfo.cc \
tinfo2.cc \
vec.cc
sources = del_op.cc del_opnt.cc del_opv.cc del_opvnt.cc eh_alloc.cc eh_aux_runtime.cc eh_catch.cc eh_exception.cc eh_globals.cc eh_personality.cc eh_terminate.cc eh_throw.cc new_handler.cc new_op.cc new_opnt.cc new_opv.cc new_opvnt.cc pure.cc tinfo.cc tinfo2.cc vec.cc
libsupc___la_SOURCES = $(sources)
@ -187,12 +167,7 @@ LIBSUPCXX_CXXFLAGS = -prefer-pic
# set this option because CONFIG_CXXFLAGS has to be after
# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden
# as the occasion call for it. (ie, --enable-debug)
AM_CXXFLAGS = \
-fno-implicit-templates \
$(LIBSUPCXX_CXXFLAGS) \
$(WARN_CXXFLAGS) \
$(OPTIMIZE_CXXFLAGS) \
$(CONFIG_CXXFLAGS)
AM_CXXFLAGS = -fno-implicit-templates $(LIBSUPCXX_CXXFLAGS) $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
# libstdc++ libtool notes
@ -216,9 +191,7 @@ AM_CXXFLAGS = \
#
# We have to put --tag disable-shared after --tag CXX lest things
# CXX undo the affect of disable-shared.
LTCXXCOMPILE = $(LIBTOOL) --tag CXX --tag disable-shared \
--mode=compile $(CXX) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(AM_CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) --tag CXX --tag disable-shared --mode=compile $(CXX) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(AM_CXXFLAGS)
# 3) We'd have a problem when building the shared libstdc++ object if
@ -227,8 +200,7 @@ LTCXXCOMPILE = $(LIBTOOL) --tag CXX --tag disable-shared \
# course is problematic at this point. So, we get the top-level
# directory to configure libstdc++-v3 to use gcc as the C++
# compilation driver.
CXXLINK = $(LIBTOOL) --tag CXX --mode=link $(CXX) \
@OPT_LDFLAGS@ @SECTION_LDFLAGS@ $(AM_CXXFLAGS) $(LDFLAGS) -o $@
CXXLINK = $(LIBTOOL) --tag CXX --mode=link $(CXX) @OPT_LDFLAGS@ @SECTION_LDFLAGS@ $(AM_CXXFLAGS) $(LDFLAGS) -o $@
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
@ -242,13 +214,16 @@ LIBS = @LIBS@
libsupc__convenience_la_LDFLAGS =
libsupc__convenience_la_LIBADD =
libsupc__convenience_la_OBJECTS = del_op.lo del_opnt.lo del_opv.lo \
del_opvnt.lo exception_support.lo new_handler.lo new_op.lo new_opnt.lo \
new_opv.lo new_opvnt.lo pure.lo tinfo.lo tinfo2.lo vec.lo
del_opvnt.lo eh_alloc.lo eh_aux_runtime.lo eh_catch.lo eh_exception.lo \
eh_globals.lo eh_personality.lo eh_terminate.lo eh_throw.lo \
new_handler.lo new_op.lo new_opnt.lo new_opv.lo new_opvnt.lo pure.lo \
tinfo.lo tinfo2.lo vec.lo
libsupc___la_LDFLAGS =
libsupc___la_LIBADD =
libsupc___la_OBJECTS = del_op.lo del_opnt.lo del_opv.lo del_opvnt.lo \
exception_support.lo new_handler.lo new_op.lo new_opnt.lo new_opv.lo \
new_opvnt.lo pure.lo tinfo.lo tinfo2.lo vec.lo
eh_alloc.lo eh_aux_runtime.lo eh_catch.lo eh_exception.lo eh_globals.lo \
eh_personality.lo eh_terminate.lo eh_throw.lo new_handler.lo new_op.lo \
new_opnt.lo new_opv.lo new_opvnt.lo pure.lo tinfo.lo tinfo2.lo vec.lo
CXXFLAGS = @CXXFLAGS@
CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
@ -417,7 +392,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
if test -f $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \

View File

@ -0,0 +1,157 @@
// -*- C++ -*- Allocate exception objects.
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This file is part of GNU CC.
//
// GNU CC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// GNU CC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU CC; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
// This is derived from the C++ ABI for IA-64. Where we diverge
// for cross-architecture compatibility are noted with "@@@".
#include <exception>
#include <cstdlib>
#include <cstring>
#include <limits.h>
#include "unwind-cxx.h"
#include "gthr.h"
using namespace __cxxabiv1;
// ??? How to control these parameters.
// Guess from the size of basic types how large a buffer is reasonable.
// Note that the basic c++ exception header has 13 pointers and 2 ints,
// so on a system with PSImode pointers we're talking about 56 bytes
// just for overhead.
#if INT_MAX == 32767
# define EMERGENCY_OBJ_SIZE 128
# define EMERGENCY_OBJ_COUNT 16
#elif LONG_MAX == 2147483647
# define EMERGENCY_OBJ_SIZE 512
# define EMERGENCY_OBJ_COUNT 32
#else
# define EMERGENCY_OBJ_SIZE 1024
# define EMERGENCY_OBJ_COUNT 64
#endif
#ifndef __GTHREADS
# undef EMERGENCY_OBJ_COUNT
# define EMERGENCY_OBJ_COUNT 4
#endif
#if INT_MAX == 32767 || EMERGENCY_OBJ_COUNT <= 32
typedef unsigned int bitmask_type;
#else
typedef unsigned long bitmask_type;
#endif
typedef char one_buffer[EMERGENCY_OBJ_SIZE] __attribute__((aligned));
static one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT];
static bitmask_type emergency_used;
#ifdef __GTHREADS
#ifdef __GTHREAD_MUTEX_INIT
static __gthread_mutex_t emergency_mutex =__GTHREAD_MUTEX_INIT;
#else
static __gthread_mutex_t emergency_mutex;
#endif
#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
static void
emergency_mutex_init ()
{
__GTHREAD_MUTEX_INIT_FUNCTION (&emergency_mutex);
}
#endif
#endif
extern "C" void *
__cxa_allocate_exception(std::size_t thrown_size)
{
void *ret;
thrown_size += sizeof (__cxa_exception);
ret = malloc (thrown_size);
if (! ret)
{
#ifdef __GTHREADS
#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
__gthread_once (&once, emergency_mutex_init);
#endif
__gthread_mutex_lock (&emergency_mutex);
#endif
bitmask_type used = emergency_used;
unsigned int which = 0;
while (used & 1)
{
used >>= 1;
if (++which >= EMERGENCY_OBJ_COUNT)
std::terminate ();
}
emergency_used |= (bitmask_type)1 << which;
ret = &emergency_buffer[which][0];
#ifdef __GTHREADS
__gthread_mutex_unlock (&emergency_mutex);
#endif
}
memset (ret, 0, sizeof (__cxa_exception));
return (void *)((char *)ret + sizeof (__cxa_exception));
}
extern "C" void
__cxa_free_exception(void *vptr)
{
char *ptr = (char *) vptr;
if (ptr >= &emergency_buffer[0][0]
&& ptr < &emergency_buffer[0][0] + sizeof (emergency_buffer))
{
unsigned int which
= (unsigned)(ptr - &emergency_buffer[0][0]) / EMERGENCY_OBJ_SIZE;
#ifdef __GTHREADS
__gthread_mutex_lock (&emergency_mutex);
emergency_used &= ~((bitmask_type)1 << which);
__gthread_mutex_unlock (&emergency_mutex);
#else
emergency_used &= ~((bitmask_type)1 << which);
#endif
}
else
free (ptr - sizeof (__cxa_exception));
}

View File

@ -0,0 +1,56 @@
// -*- C++ -*- Common throw conditions.
// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
// Free Software Foundation
//
// This file is part of GNU CC.
//
// GNU CC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// GNU CC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU CC; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
#include "typeinfo"
#include "exception"
#include <cstddef>
#include "unwind-cxx.h"
#include "exception_defines.h"
extern "C" void
__cxa_bad_cast ()
{
#ifdef __EXCEPTIONS
throw std::bad_cast();
#else
std::abort();
#endif
}
extern "C" void
__cxa_bad_typeid ()
{
#ifdef __EXCEPTIONS
throw std::bad_typeid();
#else
std::abort();
#endif
}

View File

@ -0,0 +1,103 @@
// -*- C++ -*- Exception handling routines for catching.
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This file is part of GNU CC.
//
// GNU CC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// GNU CC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU CC; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
#include <cstdlib>
#include "unwind-cxx.h"
using namespace __cxxabiv1;
extern "C" void *
__cxa_begin_catch (_Unwind_Exception *exceptionObject)
{
// ??? Foreign exceptions can't be stacked here, and there doesn't
// appear to be any place to store for __cxa_end_catch to destroy.
__cxa_exception *header = __get_exception_header_from_ue (exceptionObject);
__cxa_eh_globals *globals = __cxa_get_globals ();
__cxa_exception *prev = globals->caughtExceptions;
int count = header->handlerCount;
if (count < 0)
// This exception was rethrown from an immediately enclosing region.
count = -count + 1;
else
count += 1;
header->handlerCount = count;
globals->uncaughtExceptions -= 1;
if (header != prev)
{
header->nextException = prev;
globals->caughtExceptions = header;
}
return header->adjustedPtr;
}
extern "C" void
__cxa_end_catch ()
{
__cxa_eh_globals *globals = __cxa_get_globals_fast ();
__cxa_exception *header = globals->caughtExceptions;
int count = header->handlerCount;
if (count < 0)
{
// This exception was rethrown. Decrement the (inverted) catch
// count and remove it from the chain when it reaches zero.
if (++count == 0)
{
globals->uncaughtExceptions += 1;
globals->caughtExceptions = header->nextException;
}
}
else if (--count == 0)
{
// Handling for this exception is complete. Destroy the object.
globals->caughtExceptions = header->nextException;
_Unwind_DeleteException (&header->unwindHeader);
return;
}
else if (count < 0)
// A bug in the exception handling library or compiler.
abort ();
header->handlerCount = count;
}
bool
std::uncaught_exception() throw()
{
__cxa_eh_globals *globals = __cxa_get_globals ();
return globals->uncaughtExceptions != 0;
}

View File

@ -0,0 +1,44 @@
// -*- C++ -*- std::exception implementation.
// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
// Free Software Foundation
//
// This file is part of GNU CC.
//
// GNU CC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// GNU CC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU CC; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
#include "typeinfo"
#include "exception"
#include "unwind-cxx.h"
std::exception::~exception() throw() { }
std::bad_exception::~bad_exception() throw() { }
const char*
std::exception::what() const throw()
{
return typeid (*this).name ();
}

View File

@ -0,0 +1,120 @@
// -*- C++ -*- Manage the thread-local exception globals.
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This file is part of GNU CC.
//
// GNU CC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// GNU CC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU CC; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
#include <exception>
#include "unwind-cxx.h"
#include "gthr.h"
using namespace __cxxabiv1;
// Single-threaded fallback buffer.
static __cxa_eh_globals globals_static;
#if __GTHREADS
static __gthread_key_t globals_key;
static int use_thread_key = -1;
static void
get_globals_dtor (void *ptr)
{
__gthread_key_dtor (globals_key, ptr);
if (ptr)
free (ptr);
}
static void
get_globals_init ()
{
use_thread_key =
(__gthread_key_create (&globals_key, get_globals_dtor) == 0);
}
static void
get_globals_init_once ()
{
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
if (__gthread_once (&once, get_globals_init) != 0
|| use_thread_key < 0)
use_thread_key = 0;
}
#endif
extern "C" __cxa_eh_globals *
__cxa_get_globals_fast ()
{
#if __GTHREADS
if (use_thread_key)
return (__cxa_eh_globals *) __gthread_getspecific (globals_key);
else
return &globals_static;
#else
return &globals_static;
#endif
}
extern "C" __cxa_eh_globals *
__cxa_get_globals ()
{
#if __GTHREADS
__cxa_eh_globals *g;
if (use_thread_key == 0)
return &globals_static;
if (use_thread_key < 0)
get_globals_init_once ();
g = (__cxa_eh_globals *) __gthread_getspecific (globals_key);
if (! g)
{
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
// Make sure use_thread_key got initialized. Some systems have
// dummy thread routines in their libc that return a success.
if (__gthread_once (&once, eh_threads_initialize) != 0
|| use_thread_key < 0)
{
use_thread_key = 0;
return &globals_static;
}
if ((g = malloc (sizeof (__cxa_eh_globals))) == 0
|| __gthread_setspecific (eh_context_key, (void *) g) != 0)
std::terminate ();
g->caughtExceptions = 0;
g->uncaughtExceptions = 0;
}
return g;
#else
return &globals_static;
#endif
}

View File

@ -0,0 +1,599 @@
// -*- C++ -*- The GNU C++ exception personality routine.
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This file is part of GNU CC.
//
// GNU CC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// GNU CC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU CC; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
#include <bits/c++config.h>
#include <cstdlib>
#include "unwind-cxx.h"
using namespace __cxxabiv1;
// ??? These ought to go somewhere else dwarf2 or dwarf2eh related.
// Pointer encodings.
#define DW_EH_PE_absptr 0x00
#define DW_EH_PE_omit 0xff
#define DW_EH_PE_uleb128 0x01
#define DW_EH_PE_udata2 0x02
#define DW_EH_PE_udata4 0x03
#define DW_EH_PE_udata8 0x04
#define DW_EH_PE_sleb128 0x09
#define DW_EH_PE_sdata2 0x0A
#define DW_EH_PE_sdata4 0x0B
#define DW_EH_PE_sdata8 0x0C
#define DW_EH_PE_signed 0x08
#define DW_EH_PE_pcrel 0x10
#define DW_EH_PE_textrel 0x20
#define DW_EH_PE_datarel 0x30
#define DW_EH_PE_funcrel 0x40
static unsigned int
size_of_encoded_value (unsigned char encoding)
{
switch (encoding & 0x07)
{
case DW_EH_PE_absptr:
return sizeof (void *);
case DW_EH_PE_udata2:
return 2;
case DW_EH_PE_udata4:
return 4;
case DW_EH_PE_udata8:
return 8;
}
abort ();
}
static const unsigned char *
read_encoded_value (_Unwind_Context *context, unsigned char encoding,
const unsigned char *p, _Unwind_Ptr *val)
{
union unaligned
{
void *ptr;
unsigned u2 __attribute__ ((mode (HI)));
unsigned u4 __attribute__ ((mode (SI)));
unsigned u8 __attribute__ ((mode (DI)));
signed s2 __attribute__ ((mode (HI)));
signed s4 __attribute__ ((mode (SI)));
signed s8 __attribute__ ((mode (DI)));
} __attribute__((__packed__));
union unaligned *u = (union unaligned *) p;
_Unwind_Ptr result;
switch (encoding & 0x0f)
{
case DW_EH_PE_absptr:
result = (_Unwind_Ptr) u->ptr;
p += sizeof (void *);
break;
case DW_EH_PE_uleb128:
{
unsigned int shift = 0;
unsigned char byte;
result = 0;
do
{
byte = *p++;
result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
shift += 7;
}
while (byte & 0x80);
}
break;
case DW_EH_PE_sleb128:
{
unsigned int shift = 0;
unsigned char byte;
result = 0;
do
{
byte = *p++;
result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
shift += 7;
}
while (byte & 0x80);
if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
result |= -(1L << shift);
}
break;
case DW_EH_PE_udata2:
result = u->u2;
p += 2;
break;
case DW_EH_PE_udata4:
result = u->u4;
p += 4;
break;
case DW_EH_PE_udata8:
result = u->u8;
p += 8;
break;
case DW_EH_PE_sdata2:
result = u->s2;
p += 2;
break;
case DW_EH_PE_sdata4:
result = u->s4;
p += 4;
break;
case DW_EH_PE_sdata8:
result = u->s8;
p += 8;
break;
default:
abort ();
}
if (result != 0)
switch (encoding & 0xf0)
{
case DW_EH_PE_absptr:
break;
case DW_EH_PE_pcrel:
// Define as relative to the beginning of the pointer.
result += (_Unwind_Ptr) u;
break;
case DW_EH_PE_textrel:
case DW_EH_PE_datarel:
// FIXME.
abort ();
case DW_EH_PE_funcrel:
result += _Unwind_GetRegionStart (context);
break;
default:
abort ();
}
*val = result;
return p;
}
static inline const unsigned char *
read_uleb128 (const unsigned char *p, _Unwind_Ptr *val)
{
return read_encoded_value (0, DW_EH_PE_uleb128, p, val);
}
static inline const unsigned char *
read_sleb128 (const unsigned char *p, _Unwind_Ptr *val)
{
return read_encoded_value (0, DW_EH_PE_sleb128, p, val);
}
struct lsda_header_info
{
_Unwind_Ptr Start;
_Unwind_Ptr LPStart;
const unsigned char *TType;
const unsigned char *action_table;
unsigned char ttype_encoding;
unsigned char call_site_encoding;
};
static const unsigned char *
parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
lsda_header_info *info)
{
_Unwind_Ptr tmp;
unsigned char lpstart_encoding;
info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
// Find @LPStart, the base to which landing pad offsets are relative.
lpstart_encoding = *p++;
if (lpstart_encoding != DW_EH_PE_omit)
p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
else
info->LPStart = info->Start;
// Find @TType, the base of the handler and exception spec type data.
info->ttype_encoding = *p++;
if (info->ttype_encoding != DW_EH_PE_omit)
{
p = read_uleb128 (p, &tmp);
info->TType = p + tmp;
}
else
info->TType = 0;
// The encoding and length of the call-site table; the action table
// immediately follows.
info->call_site_encoding = *p++;
p = read_uleb128 (p, &tmp);
info->action_table = p + tmp;
return p;
}
static const std::type_info *
get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
{
_Unwind_Ptr ptr;
i *= size_of_encoded_value (info->ttype_encoding);
read_encoded_value (context, info->ttype_encoding, info->TType - i, &ptr);
return reinterpret_cast<const std::type_info *>(ptr);
}
static bool
check_exception_spec (_Unwind_Context *context, lsda_header_info *info,
const std::type_info *throw_type, long filter_value)
{
const unsigned char *e = info->TType - filter_value - 1;
while (1)
{
const std::type_info *catch_type;
_Unwind_Ptr tmp;
void *dummy;
e = read_uleb128 (e, &tmp);
// Zero signals the end of the list. If we've not found
// a match by now, then we've failed the specification.
if (tmp == 0)
return false;
// Match a ttype entry.
catch_type = get_ttype_entry (context, info, tmp);
if (catch_type->__do_catch (throw_type, &dummy, 1))
return true;
}
}
// Using a different personality function name causes link failures
// when trying to mix code using different exception handling models.
#ifdef _GLIBCPP_SJLJ_EXCEPTIONS
#define PERSONALITY_FUNCTION __gxx_personality_sj0
#define __builtin_eh_return_data_regno(x) x
#else
#define PERSONALITY_FUNCTION __gxx_personality_v0
#endif
extern "C" _Unwind_Reason_Code
PERSONALITY_FUNCTION (int version,
_Unwind_Action actions,
_Unwind_Exception_Class exception_class,
struct _Unwind_Exception *ue_header,
struct _Unwind_Context *context)
{
__cxa_exception *xh = __get_exception_header_from_ue (ue_header);
enum found_handler_type
{
found_nothing,
found_terminate,
found_cleanup,
found_handler
} found_type;
lsda_header_info info;
const unsigned char *language_specific_data;
const unsigned char *action_record;
const unsigned char *p;
_Unwind_Ptr landing_pad, ip;
int handler_switch_value;
void *adjusted_ptr = xh + 1;
// Interface version check.
if (version != 1)
return _URC_FATAL_PHASE1_ERROR;
// Shortcut for phase 2 found handler for domestic exception.
if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
&& exception_class == __gxx_exception_class)
{
handler_switch_value = xh->handlerSwitchValue;
landing_pad = (_Unwind_Ptr) xh->catchTemp;
found_type = (landing_pad == 0 ? found_terminate : found_handler);
goto install_context;
}
language_specific_data = (const unsigned char *)
_Unwind_GetLanguageSpecificData (context);
// If no LSDA, then there are no handlers or cleanups.
if (! language_specific_data)
return _URC_CONTINUE_UNWIND;
// Parse the LSDA header.
p = parse_lsda_header (context, language_specific_data, &info);
ip = _Unwind_GetIP (context) - 1;
landing_pad = 0;
action_record = 0;
handler_switch_value = 0;
#ifdef _GLIBCPP_SJLJ_EXCEPTIONS
// The given "IP" is an index into the call-site table, with two
// exceptions -- -1 means no-action, and 0 means terminate. But
// since we're using uleb128 values, we've not got random access
// to the array.
if ((int) ip < 0)
return _URC_CONTINUE_UNWIND;
else if (ip == 0)
{
// Fall through to set found_terminate.
}
else
{
_Unwind_Ptr cs_lp, cs_action;
do
{
p = read_uleb128 (p, &cs_lp);
p = read_uleb128 (p, &cs_action);
}
while (--ip);
// Can never have null landing pad for sjlj -- that would have
// been indicated by a -1 call site index.
landing_pad = cs_lp + 1;
if (cs_action)
action_record = info.action_table + cs_action - 1;
goto found_something;
}
#else
// Search the call-site table for the action associated with this IP.
while (p < info.action_table)
{
_Unwind_Ptr cs_start, cs_len, cs_lp, cs_action;
// Note that all call-site encodings are "absolute" displacements.
p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
p = read_uleb128 (p, &cs_action);
// The table is sorted, so if we've passed the ip, stop.
if (ip < info.Start + cs_start)
p = info.action_table;
else if (ip < info.Start + cs_start + cs_len)
{
if (cs_lp)
landing_pad = info.LPStart + cs_lp;
if (cs_action)
action_record = info.action_table + cs_action - 1;
goto found_something;
}
}
#endif // _GLIBCPP_SJLJ_EXCEPTIONS
// If ip is not present in the table, call terminate. This is for
// a destructor inside a cleanup, or a library routine the compiler
// was not expecting to throw.
found_type = (actions & _UA_FORCE_UNWIND ? found_nothing : found_terminate);
goto do_something;
found_something:
if (landing_pad == 0)
{
// If ip is present, and has a null landing pad, there are
// no cleanups or handlers to be run.
found_type = found_nothing;
}
else if (action_record == 0)
{
// If ip is present, has a non-null landing pad, and a null
// action table offset, then there are only cleanups present.
// Cleanups use a zero switch value, as set above.
found_type = found_cleanup;
}
else
{
// Otherwise we have a catch handler or exception specification.
signed long ar_filter, ar_disp;
const std::type_info *throw_type, *catch_type;
bool saw_cleanup = false;
bool saw_handler = false;
// During forced unwinding, we only run cleanups. With a foreign
// exception class, there's no exception type.
// ??? What to do about GNU Java and GNU Ada exceptions.
if ((actions & _UA_FORCE_UNWIND)
|| exception_class != __gxx_exception_class)
throw_type = 0;
else
throw_type = xh->exceptionType;
while (1)
{
_Unwind_Ptr tmp;
p = action_record;
p = read_sleb128 (p, &tmp); ar_filter = tmp;
read_sleb128 (p, &tmp); ar_disp = tmp;
if (ar_filter == 0)
{
// Zero filter values are cleanups.
saw_cleanup = true;
}
else if (ar_filter > 0)
{
// Positive filter values are handlers.
catch_type = get_ttype_entry (context, &info, ar_filter);
adjusted_ptr = xh + 1;
// Null catch type is a catch-all handler. We can catch
// foreign exceptions with this.
if (! catch_type)
{
if (!(actions & _UA_FORCE_UNWIND))
{
saw_handler = true;
break;
}
}
else if (throw_type)
{
// Pointer types need to adjust the actual pointer, not
// the pointer to pointer that is the exception object.
// This also has the effect of passing pointer types
// "by value" through the __cxa_begin_catch return value.
if (throw_type->__is_pointer_p ())
adjusted_ptr = *(void **) adjusted_ptr;
if (catch_type->__do_catch (throw_type, &adjusted_ptr, 1))
{
saw_handler = true;
break;
}
}
}
else
{
// Negative filter values are exception specifications.
// ??? How do foreign exceptions fit in? As far as I can
// see we can't match because there's no __cxa_exception
// object to stuff bits in for __cxa_call_unexpected to use.
if (throw_type
&& ! check_exception_spec (context, &info, throw_type,
ar_filter))
{
saw_handler = true;
break;
}
}
if (ar_disp == 0)
break;
action_record = p + ar_disp;
}
if (saw_handler)
{
handler_switch_value = ar_filter;
found_type = found_handler;
}
else
found_type = (saw_cleanup ? found_cleanup : found_nothing);
}
do_something:
if (found_type == found_nothing)
return _URC_CONTINUE_UNWIND;
if (actions & _UA_SEARCH_PHASE)
{
if (found_type == found_cleanup)
return _URC_CONTINUE_UNWIND;
// For domestic exceptions, we cache data from phase 1 for phase 2.
if (exception_class == __gxx_exception_class)
{
xh->handlerSwitchValue = handler_switch_value;
xh->actionRecord = action_record;
xh->languageSpecificData = language_specific_data;
xh->adjustedPtr = adjusted_ptr;
// ??? Completely unknown what this field is supposed to be for.
// ??? Need to cache TType encoding base for call_unexpected.
xh->catchTemp = (void *) (_Unwind_Ptr) landing_pad;
}
return _URC_HANDLER_FOUND;
}
install_context:
if (found_type == found_terminate)
{
__cxa_begin_catch (&xh->unwindHeader);
__terminate (xh->terminateHandler);
}
_Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
(_Unwind_Ptr) &xh->unwindHeader);
_Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
handler_switch_value);
_Unwind_SetIP (context, landing_pad);
return _URC_INSTALL_CONTEXT;
}
extern "C" void
__cxa_call_unexpected (_Unwind_Exception *exc_obj)
{
__cxa_begin_catch (exc_obj);
// This function is a handler for our exception argument. If we exit
// by throwing a different exception, we'll need the original cleaned up.
struct end_catch_protect
{
end_catch_protect() { }
~end_catch_protect() { __cxa_end_catch(); }
} end_catch_protect_obj;
__cxa_exception *xh = __get_exception_header_from_ue (exc_obj);
try {
__unexpected (xh->unexpectedHandler);
} catch (...) {
// Get the exception thrown from unexpected.
// ??? Foreign exceptions can't be stacked this way.
__cxa_eh_globals *globals = __cxa_get_globals_fast ();
__cxa_exception *new_xh = globals->caughtExceptions;
// We don't quite have enough stuff cached; re-parse the LSDA.
lsda_header_info info;
parse_lsda_header (0, xh->languageSpecificData, &info);
// If this new exception meets the exception spec, allow it.
if (check_exception_spec (0, &info, new_xh->exceptionType,
xh->handlerSwitchValue))
throw;
// If the exception spec allows std::bad_exception, throw that.
const std::type_info &bad_exc = typeid (std::bad_exception);
if (check_exception_spec (0, &info, &bad_exc, xh->handlerSwitchValue))
throw std::bad_exception ();
// Otherwise, die.
__terminate(xh->terminateHandler);
}
}

View File

@ -0,0 +1,87 @@
// -*- C++ -*- std::terminate, std::unexpected and friends.
// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
// Free Software Foundation
//
// This file is part of GNU CC.
//
// GNU CC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// GNU CC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU CC; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
#include "typeinfo"
#include "exception"
#include <cstdlib>
#include "unwind-cxx.h"
#include "exception_defines.h"
using namespace __cxxabiv1;
/* The current installed user handlers. */
std::terminate_handler __cxxabiv1::__terminate_handler = abort;
std::unexpected_handler __cxxabiv1::__unexpected_handler = std::terminate;
void
__cxxabiv1::__terminate (std::terminate_handler handler)
{
try {
handler ();
abort ();
} catch (...) {
abort ();
}
}
void
std::terminate ()
{
__terminate (__terminate_handler);
}
void
__cxxabiv1::__unexpected (std::unexpected_handler handler)
{
handler();
std::terminate ();
}
void
std::unexpected ()
{
__unexpected (__unexpected_handler);
}
std::terminate_handler
std::set_terminate (std::terminate_handler func) throw()
{
std::terminate_handler old = __terminate_handler;
__terminate_handler = func;
return old;
}
std::unexpected_handler
std::set_unexpected (std::unexpected_handler func) throw()
{
std::unexpected_handler old = __unexpected_handler;
__unexpected_handler = func;
return old;
}

View File

@ -0,0 +1,102 @@
// -*- C++ -*- Exception handling routines for throwing.
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This file is part of GNU CC.
//
// GNU CC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// GNU CC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU CC; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
#include <bits/c++config.h>
#include "unwind-cxx.h"
using namespace __cxxabiv1;
static void
__gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
{
__cxa_exception *header = __get_exception_header_from_ue (exc);
// If we havn't been caught by a foreign handler, then this is
// some sort of unwind error. In that case just die immediately.
if (code != _URC_FOREIGN_EXCEPTION_CAUGHT)
__terminate (header->terminateHandler);
if (header->exceptionDestructor)
header->exceptionDestructor (header + 1);
__cxa_free_exception (header + 1);
}
extern "C" void
__cxa_throw (void *obj, std::type_info *tinfo, void (*dest) (void *))
{
__cxa_exception *header = __get_exception_header_from_obj (obj);
header->exceptionType = tinfo;
header->exceptionDestructor = dest;
header->unexpectedHandler = __unexpected_handler;
header->terminateHandler = __terminate_handler;
header->unwindHeader.exception_class = __gxx_exception_class;
header->unwindHeader.exception_cleanup = __gxx_exception_cleanup;
__cxa_eh_globals *globals = __cxa_get_globals ();
globals->uncaughtExceptions += 1;
#ifdef _GLIBCPP_SJLJ_EXCEPTIONS
_Unwind_SjLj_RaiseException (&header->unwindHeader);
#else
_Unwind_RaiseException (&header->unwindHeader);
#endif
// Some sort of unwinding error. Note that terminate is a handler.
__cxa_begin_catch (&header->unwindHeader);
std::terminate ();
}
extern "C" void
__cxa_rethrow ()
{
__cxa_eh_globals *globals = __cxa_get_globals ();
__cxa_exception *header = globals->caughtExceptions;
// Watch for luser rethrowing with no active exception.
if (header)
{
// Tell __cxa_end_catch this is a rethrow.
header->handlerCount = -header->handlerCount;
#ifdef _GLIBCPP_SJLJ_EXCEPTIONS
_Unwind_SjLj_RaiseException (&header->unwindHeader);
#else
_Unwind_RaiseException (&header->unwindHeader);
#endif
// Some sort of unwinding error. Note that terminate is a handler.
__cxa_begin_catch (&header->unwindHeader);
}
std::terminate ();
}

View File

@ -1,388 +0,0 @@
// Functions for Exception Support for -*- C++ -*-
// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
// Free Software Foundation
//
// This file is part of GNU CC.
//
// GNU CC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
// GNU CC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with GNU CC; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
#include "typeinfo"
#include "exception"
#include <cstddef>
#include "exception_support.h"
#include "exception_defines.h"
/* Define terminate, unexpected, set_terminate, set_unexpected as
well as the default terminate func and default unexpected func. */
/* __terminate and __terminate_set_func, defined in libgcc2. */
typedef void (*__terminate_func_ptr)(void) __attribute__ ((__noreturn__));
extern "C" void __terminate (void) __attribute__ ((__noreturn__));
extern "C" __terminate_func_ptr __terminate_set_func (__terminate_func_ptr);
using std::terminate;
void
std::terminate ()
{
__terminate ();
}
void
__default_unexpected ()
{
terminate ();
}
static std::unexpected_handler __unexpected_func __attribute__((__noreturn__))
= __default_unexpected;
std::terminate_handler
std::set_terminate (std::terminate_handler func) throw()
{
return __terminate_set_func (func);
}
std::unexpected_handler
std::set_unexpected (std::unexpected_handler func) throw()
{
std::unexpected_handler old = __unexpected_func;
__unexpected_func = func;
return old;
}
void
std::unexpected ()
{
__unexpected_func ();
}
/* Language-specific EH info pointer, defined in libgcc2. */
extern "C" cp_eh_info **__get_eh_info (); // actually void **
#define CP_EH_INFO ((cp_eh_info *) *__get_eh_info ())
/* Exception allocate and free, defined in libgcc2. */
extern "C" void *__eh_alloc(std::size_t);
extern "C" void __eh_free(void *);
/* Is P the type_info node for a pointer of some kind? */
extern bool __is_pointer (void *);
#ifdef __EXCEPTIONS
/* 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);
}
/* Old Compiler hook to return a pointer to the info for the current exception.
Used by get_eh_info (). */
extern "C" cp_eh_info *
__cp_eh_info (void)
{
cp_eh_info *p = CP_EH_INFO;
return p;
}
/* Compiler hook to return a pointer to the info for the current exception,
Set the caught bit, and increment the number of handlers that are
looking at this exception. This makes handlers smaller. */
extern "C" cp_eh_info *
__start_cp_handler (void)
{
cp_eh_info *p = CP_EH_INFO;
p->caught = 1;
p->handlers++;
return p;
}
extern "C" int __throw_type_match_rtti_2 (const void *, const void *,
void *, void **);
extern "C" void *
__cplus_type_matcher (__eh_info *info_, void *match_info,
exception_descriptor *exception_table)
{
cp_eh_info *info = (cp_eh_info *)info_;
/* No exception table implies the old style mechanism, so don't check. */
if (exception_table != NULL
&& exception_table->lang.language != EH_LANG_C_plus_plus)
return NULL;
if (match_info == CATCH_ALL_TYPE)
return (void *)1;
/* we don't worry about version info yet, there is only one version! */
void *match_type = match_info;
if (__throw_type_match_rtti_2 (match_type, info->type,
info->original_value, &info->value))
// Arbitrary non-null pointer.
return (void *)1;
else
return NULL;
}
/* Compiler hook to push a new exception onto the stack.
Used by expand_throw(). */
extern "C" void
__cp_push_exception (void *value, void *type, cleanup_fn cleanup)
{
cp_eh_info *p = (cp_eh_info *) __eh_alloc (sizeof (cp_eh_info));
p->value = value;
p->type = type;
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;
cp_eh_info **q = __get_eh_info ();
p->next = *q;
*q = p;
}
/* Compiler hook to pop an exception that has been finalized. Used by
push_eh_cleanup(). P is the info for the exception caught by the
current catch block. */
extern "C" void
__cp_pop_exception (void* p_)
{
cp_eh_info *p = static_cast <cp_eh_info *> (p_);
cp_eh_info **stack = __get_eh_info ();
cp_eh_info **q = stack;
--p->handlers;
/* Do nothing if our exception is being rethrown (i.e. if the active
exception is our exception and it is uncaught). */
if (p == *q && !p->caught)
return;
/* Don't really pop if there are still active handlers for our exception;
rather, push it down past any uncaught exceptions. */
if (p->handlers != 0)
{
if (p == *q && p->next && !p->next->caught)
{
q = &(p->next);
while (1)
{
if (*q == 0 || (*q)->caught)
break;
q = &((*q)->next);
}
*stack = p->next;
p->next = *q;
*q = p;
}
return;
}
for (; *q; q = &((*q)->next))
if (*q == p)
break;
if (! *q)
terminate ();
*q = p->next;
if (p->cleanup)
// value may have been adjusted.
CALL_CLEANUP (p->cleanup, p->original_value);
if (! __is_pointer (p->type))
__eh_free (p->original_value); // value may have been adjusted.
__eh_free (p);
}
/* We're doing a rethrow. Find the currently handled exception, mark it
uncaught, and move it to the top of the EH stack. */
extern "C" cp_eh_info *
__uncatch_exception (void)
{
cp_eh_info **stack = __get_eh_info ();
cp_eh_info **q = stack;
cp_eh_info *p;
while (1)
{
p = *q;
if (p == 0)
terminate ();
if (p->caught)
break;
q = &(p->next);
}
if (q != stack)
{
*q = p->next;
p->next = *stack;
*stack = p;
}
p->caught = false;
return p;
}
/* Mark P as caught after we previously marked it as uncaught. */
extern "C" void
__recatch_exception (cp_eh_info *p)
{
p->caught = true;
}
/* As per [except.unexpected]:
If an exception is thrown, we check it against the spec. If it doesn't
match, we call unexpected (). If unexpected () throws, we check that
exception against the spec. If it doesn't match, if the spec allows
bad_exception we throw that; otherwise we call terminate ().
The compiler treats an exception spec as a try block with a generic
handler that just calls this function with a list of the allowed
exception types, so we have an active exception that can be rethrown.
This function does not return. */
extern "C" void
__check_eh_spec (int n, const void **spec)
{
cp_eh_info *p = CP_EH_INFO;
void *d;
for (int i = 0; i < n; ++i)
{
if (__throw_type_match_rtti_2 (spec[i], p->type, p->value, &d))
throw;
}
try
{
std::unexpected ();
}
catch (...)
{
// __exception_info is an artificial var pushed into each catch block.
if (p != __exception_info)
{
p = __exception_info;
for (int i = 0; i < n; ++i)
{
if (__throw_type_match_rtti_2 (spec[i], p->type, p->value, &d))
throw;
}
}
const std::type_info &bad_exc = typeid (std::bad_exception);
for (int i = 0; i < n; ++i)
{
if (__throw_type_match_rtti_2 (spec[i], &bad_exc, p->value, &d))
throw std::bad_exception ();
}
terminate ();
}
}
/* Special case of the above for throw() specs. */
extern "C" void
__check_null_eh_spec (void)
{
__check_eh_spec (0, 0);
}
#endif //__EXCEPTIONS
// Helpers for rtti. Although these don't return, we give them return types so
// that the type system is not broken.
extern "C" void *
__cxa_bad_cast ()
{
#ifdef __EXCEPTIONS
throw std::bad_cast();
#else
std::abort();
#endif
return 0;
}
extern "C" std::type_info const &
__cxa_bad_typeid ()
{
#ifdef __EXCEPTIONS
throw std::bad_typeid();
#else
std::abort();
#endif
return typeid (void);
}
/* Has the current exception been caught? */
bool
std::uncaught_exception() throw()
{
cp_eh_info *p = CP_EH_INFO;
return p && ! p->caught;
}
std::exception::~exception() throw() { }
std::bad_exception::~bad_exception() throw() { }
const char*
std::exception::what() const throw()
{ return typeid (*this).name (); }

View File

@ -1,65 +0,0 @@
// Copyright (C) 2000 Free Software Foundation, Inc.
//
// GNU CC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
// GNU CC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with GNU CC; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
#include "gansidecl.h" /* Needed to support macros used in eh-common.h. */
#include "eh-common.h"
/* The type of a function called to clean up an exception object.
(These will be destructors.) Under the old ABI, these take a
second argument (the `in-charge' argument), that indicates whether
or not do delete the object, and whether or not to destroy virtual
bases. Under the new ABI, there is no second argument. */
#if !defined (__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
typedef void (*cleanup_fn)(void *, int);
/* The `2' is the value for the in-charge parameter that indicates
that virtual bases should be destroyed. */
#define CALL_CLEANUP(FN, THIS) FN (THIS, 2)
#else
typedef void (*cleanup_fn)(void *);
#define CALL_CLEANUP(FN, THIS) FN (THIS)
#endif
/* C++-specific state about the current exception. This must match
init_exception_processing().
Note that handlers and caught are not redundant; when rethrown, an
exception can have multiple active handlers and still be considered
uncaught. */
struct cp_eh_info
{
__eh_info eh_info;
void *value;
void *type;
cleanup_fn cleanup;
bool caught;
cp_eh_info *next;
long handlers;
void *original_value;
};
extern "C" cp_eh_info *__uncatch_exception (void);
extern "C" void __recatch_exception (cp_eh_info *);

View File

@ -28,6 +28,7 @@
// the GNU General Public License.
#include <bits/c++config.h>
#include "unwind-cxx.h"
#ifdef _GLIBCPP_HAVE_UNISTD_H
# include <unistd.h>
@ -42,15 +43,9 @@
# define writestr(str) fputs(str, stderr)
#endif
extern "C" {
extern void __terminate(void) __attribute__ ((__noreturn__));
void
extern "C" void
__cxa_pure_virtual (void)
{
writestr ("pure virtual method called\n");
__terminate ();
}
std::terminate ();
}

View File

@ -165,31 +165,3 @@ __pointer_catch (const __pbase_type_info *thr_type,
}
} // namespace std
// Entry points for the compiler.
/* Low level match routine used by compiler to match types of catch
variables and thrown objects. */
extern "C" int
__throw_type_match_rtti_2 (const void *catch_type_r, const void *throw_type_r,
void *objptr, void **valp)
{
const type_info &catch_type = *(const type_info *)catch_type_r;
const type_info &throw_type = *(const type_info *)throw_type_r;
*valp = objptr;
return catch_type.__do_catch (&throw_type, valp, 1);
}
/* Called from __cp_pop_exception. Is P the type_info node for a pointer
of some kind? */
bool
__is_pointer (void *p)
{
const type_info *t = reinterpret_cast <const type_info *>(p);
return t->__is_pointer_p ();
}

View File

@ -0,0 +1,163 @@
// -*- C++ -*- Exception handling and frame unwind runtime interface routines.
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This file is part of GNU CC.
//
// GNU CC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// GNU CC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU CC; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// This is derived from the C++ ABI for IA-64. Where we diverge
// for cross-architecture compatibility are noted with "@@@".
#ifndef __UNWIND_CXX_H
#define __UNWIND_CXX_H 1
// Level 2: C++ ABI
#include <typeinfo>
#include <exception>
#include <cstddef>
#include "unwind.h"
namespace __cxxabiv1
{
// A C++ exception object consists of a header, which is a wrapper around
// an unwind object header with additional C++ specific information,
// followed by the exception object itself.
struct __cxa_exception
{
// Manage the exception object itself.
std::type_info *exceptionType;
void (*exceptionDestructor)(void *);
// The C++ standard has entertaining rules wrt calling set_terminate
// and set_unexpected in the middle of the exception cleanup process.
std::unexpected_handler unexpectedHandler;
std::terminate_handler terminateHandler;
// The caught exception stack threads through here.
__cxa_exception *nextException;
// How many nested handlers have caught this exception. A negated
// value is a signal that this object has been rethrown.
int handlerCount;
// Cache parsed handler data from the personality routine Phase 1
// for Phase 2 and __cxa_call_unexpected.
int handlerSwitchValue;
const unsigned char *actionRecord;
const unsigned char *languageSpecificData;
void *catchTemp;
void *adjustedPtr;
// The generic exception header. Must be last.
_Unwind_Exception unwindHeader;
};
// Each thread in a C++ program has access to a __cxa_eh_globals object.
struct __cxa_eh_globals
{
__cxa_exception *caughtExceptions;
unsigned int uncaughtExceptions;
};
// The __cxa_eh_globals for the current thread can be obtained by using
// either of the following functions. The "fast" version assumes at least
// one prior call of __cxa_get_globals has been made from the current
// thread, so no initialization is necessary.
extern "C" __cxa_eh_globals *__cxa_get_globals () throw();
extern "C" __cxa_eh_globals *__cxa_get_globals_fast () throw();
// Allocate memory for the exception plus the thown object.
extern "C" void *__cxa_allocate_exception(std::size_t thrown_size) throw();
// Free the space allocated for the exception.
extern "C" void __cxa_free_exception(void *thrown_exception) throw();
// Throw the exception.
extern "C" void __cxa_throw (void *thrown_exception,
std::type_info *tinfo,
void (*dest) (void *))
__attribute__((noreturn));
// Used to implement exception handlers.
extern "C" void *__cxa_begin_catch (_Unwind_Exception *) throw();
extern "C" void __cxa_end_catch ();
extern "C" void __cxa_rethrow () __attribute__((noreturn));
// These facilitate code generation for recurring situations.
extern "C" void __cxa_bad_cast ();
extern "C" void __cxa_bad_typeid ();
// @@@ These are not directly specified by the IA-64 C++ ABI.
// Handles re-checking the exception specification if unexpectedHandler
// throws, and if bad_exception needs to be thrown. Called from the
// compiler.
extern "C" void __cxa_call_unexpected (_Unwind_Exception *)
__attribute__((noreturn));
// Invokes given handler, dying appropriately if the user handler was
// so inconsiderate as to return.
extern void __terminate(std::terminate_handler) __attribute__((noreturn));
extern void __unexpected(std::unexpected_handler) __attribute__((noreturn));
// The current installed user handlers.
extern std::terminate_handler __terminate_handler;
extern std::unexpected_handler __unexpected_handler;
// These are explicitly GNU C++ specific.
// This is the exception class we report -- "GNUCC++\0".
const _Unwind_Exception_Class __gxx_exception_class
= ((((((((_Unwind_Exception_Class) 'G'
<< 8 | (_Unwind_Exception_Class) 'N')
<< 8 | (_Unwind_Exception_Class) 'U')
<< 8 | (_Unwind_Exception_Class) 'C')
<< 8 | (_Unwind_Exception_Class) 'C')
<< 8 | (_Unwind_Exception_Class) '+')
<< 8 | (_Unwind_Exception_Class) '+')
<< 8 | (_Unwind_Exception_Class) '\0');
// GNU C++ personality routine, Version 0.
extern "C" _Unwind_Reason_Code __gxx_personality_v0
(int, _Unwind_Action, _Unwind_Exception_Class,
struct _Unwind_Exception *, struct _Unwind_Context *);
// GNU C++ sjlj personality routine, Version 0.
extern "C" _Unwind_Reason_Code __gxx_personality_sj0
(int, _Unwind_Action, _Unwind_Exception_Class,
struct _Unwind_Exception *, struct _Unwind_Context *);
// Acquire the C++ exception header from the C++ object.
static inline __cxa_exception *
__get_exception_header_from_obj (void *ptr)
{
return reinterpret_cast<__cxa_exception *>(ptr) - 1;
}
// Acquire the C++ exception header from the generic exception header.
static inline __cxa_exception *
__get_exception_header_from_ue (_Unwind_Exception *exc)
{
return reinterpret_cast<__cxa_exception *>(exc + 1) - 1;
}
} /* namespace __cxxabiv1 */
#endif // __UNWIND_CXX_H

View File

@ -35,7 +35,7 @@
#include <exception>
#include <exception_defines.h>
#include "exception_support.h"
#include "unwind-cxx.h"
namespace __cxxabiv1
{
@ -43,11 +43,21 @@ namespace __cxxabiv1
{
struct uncatch_exception
{
uncatch_exception () { p = __uncatch_exception (); }
~uncatch_exception () { __recatch_exception (p); }
uncatch_exception ();
~uncatch_exception () { __cxa_begin_catch (&p->unwindHeader); }
cp_eh_info *p;
__cxa_exception *p;
};
uncatch_exception::uncatch_exception ()
{
__cxa_eh_globals *globals = __cxa_get_globals_fast ();
p = globals->caughtExceptions;
p->handlerCount -= 1;
globals->caughtExceptions = p->nextException;
globals->uncaughtExceptions += 1;
}
}
// Allocate and construct array.

View File

@ -120,13 +120,11 @@ OPTIMIZE_CXXFLAGS = @OPTIMIZE_CXXFLAGS@
# These bits are all figured out from configure. Look in acinclude.m4
# or configure.in to see how they are set. See GLIBCPP_EXPORT_FLAGS
# NB: DEBUGFLAGS have to be at the end so that -O2 can be overridden.
CONFIG_CXXFLAGS = \
@EXTRA_CXX_FLAGS@ @SECTION_FLAGS@ @CSHADOW_FLAGS@ @DEBUG_FLAGS@
CONFIG_CXXFLAGS = @EXTRA_CXX_FLAGS@ @SECTION_FLAGS@ @CSHADOW_FLAGS@ @DEBUG_FLAGS@
# Warning flags to use.
WARN_CXXFLAGS = \
@WARN_FLAGS@ $(WERROR) -fdiagnostics-show-location=once
WARN_CXXFLAGS = @WARN_FLAGS@ $(WERROR) -fdiagnostics-show-location=once
# Use common includes from acinclude.m4/GLIBCPP_EXPORT_INCLUDES
@ -138,133 +136,44 @@ LIBSUPCXX_INCLUDES = @LIBSUPCXX_INCLUDES@
LIBIO_INCLUDES = @LIBIO_INCLUDES@
TOPLEVEL_INCLUDES = @TOPLEVEL_INCLUDES@
INCLUDES = \
-nostdinc++ \
-I$(GLIBCPP_INCLUDE_DIR) $(CSTD_INCLUDES) -I$(top_builddir)/include \
$(LIBSUPCXX_INCLUDES) $(LIBIO_INCLUDES) $(LIBMATH_INCLUDES) \
$(TOPLEVEL_INCLUDES)
INCLUDES = -nostdinc++ -I$(GLIBCPP_INCLUDE_DIR) $(CSTD_INCLUDES) -I$(top_builddir)/include $(LIBSUPCXX_INCLUDES) $(LIBIO_INCLUDES) $(LIBMATH_INCLUDES) $(TOPLEVEL_INCLUDES)
base_headers = \
bits/cpp_type_traits.h bits/char_traits.h bits/codecvt.h \
bits/stringfwd.h bits/std_string.h bits/basic_string.h \
bits/basic_string.tcc \
bits/generic_shadow.h bits/std_utility.h \
bits/std_complex.h \
bits/valarray_array.h bits/valarray_array.tcc bits/valarray_meta.h \
bits/std_valarray.h bits/mask_array.h bits/slice.h bits/slice_array.h \
bits/gslice.h bits/gslice_array.h bits/indirect_array.h \
bits/std_fstream.h bits/std_iomanip.h \
bits/ios_base.h bits/fpos.h bits/basic_ios.h bits/basic_ios.tcc \
bits/std_ios.h bits/std_iosfwd.h bits/std_iostream.h \
bits/std_istream.h bits/istream.tcc bits/std_locale.h \
bits/fstream.tcc bits/ostream.tcc bits/sbuf_iter.h bits/sstream.tcc \
bits/std_ostream.h bits/std_sstream.h bits/std_streambuf.h \
bits/streambuf.tcc bits/basic_file.h \
bits/locale_facets.h bits/locale_facets.tcc bits/localefwd.h \
bits/stl_pthread_alloc.h bits/pthread_allocimpl.h \
bits/stl_threads.h bits/stl_iterator_base.h \
bits/std_bitset.h bits/std_deque.h bits/std_functional.h \
bits/std_iterator.h bits/std_list.h \
bits/std_map.h bits/std_memory.h bits/std_numeric.h \
bits/std_queue.h bits/std_set.h bits/std_stack.h \
bits/std_stdexcept.h bits/functexcept.h bits/std_vector.h \
bits/stl_algo.h bits/stl_algobase.h bits/stl_alloc.h \
bits/stl_deque.h bits/stl_function.h \
bits/stl_heap.h bits/stl_iterator.h bits/stl_list.h bits/stl_map.h \
bits/stl_multimap.h bits/stl_multiset.h bits/stl_numeric.h \
bits/stl_pair.h bits/stl_queue.h bits/stl_raw_storage_iter.h \
bits/stl_relops.h bits/stl_set.h \
bits/stl_stack.h bits/stl_tempbuf.h \
bits/stl_tree.h bits/stl_uninitialized.h bits/stl_vector.h \
bits/type_traits.h bits/std_algorithm.h \
bits/concept_checks.h bits/container_concepts.h \
bits/sequence_concepts.h bits/stl_construct.h
base_headers = bits/cpp_type_traits.h bits/char_traits.h bits/codecvt.h bits/stringfwd.h bits/std_string.h bits/basic_string.h bits/basic_string.tcc bits/generic_shadow.h bits/std_utility.h bits/std_complex.h bits/valarray_array.h bits/valarray_array.tcc bits/valarray_meta.h bits/std_valarray.h bits/mask_array.h bits/slice.h bits/slice_array.h bits/gslice.h bits/gslice_array.h bits/indirect_array.h bits/std_fstream.h bits/std_iomanip.h bits/ios_base.h bits/fpos.h bits/basic_ios.h bits/basic_ios.tcc bits/std_ios.h bits/std_iosfwd.h bits/std_iostream.h bits/std_istream.h bits/istream.tcc bits/std_locale.h bits/fstream.tcc bits/ostream.tcc bits/sbuf_iter.h bits/sstream.tcc bits/std_ostream.h bits/std_sstream.h bits/std_streambuf.h bits/streambuf.tcc bits/basic_file.h bits/locale_facets.h bits/locale_facets.tcc bits/localefwd.h bits/stl_pthread_alloc.h bits/pthread_allocimpl.h bits/stl_threads.h bits/stl_iterator_base.h bits/std_bitset.h bits/std_deque.h bits/std_functional.h bits/std_iterator.h bits/std_list.h bits/std_map.h bits/std_memory.h bits/std_numeric.h bits/std_queue.h bits/std_set.h bits/std_stack.h bits/std_stdexcept.h bits/functexcept.h bits/std_vector.h bits/stl_algo.h bits/stl_algobase.h bits/stl_alloc.h bits/stl_deque.h bits/stl_function.h bits/stl_heap.h bits/stl_iterator.h bits/stl_list.h bits/stl_map.h bits/stl_multimap.h bits/stl_multiset.h bits/stl_numeric.h bits/stl_pair.h bits/stl_queue.h bits/stl_raw_storage_iter.h bits/stl_relops.h bits/stl_set.h bits/stl_stack.h bits/stl_tempbuf.h bits/stl_tree.h bits/stl_uninitialized.h bits/stl_vector.h bits/type_traits.h bits/std_algorithm.h bits/concept_checks.h bits/container_concepts.h bits/sequence_concepts.h bits/stl_construct.h
backward_headers = \
backward/complex.h backward/iomanip.h backward/istream.h \
backward/ostream.h backward/stream.h backward/streambuf.h \
backward/algo.h backward/algobase.h backward/alloc.h \
backward/bvector.h backward/defalloc.h backward/deque.h \
backward/function.h backward/hash_map.h backward/hash_set.h \
backward/hashtable.h backward/heap.h backward/iterator.h \
backward/list.h backward/map.h backward/multimap.h backward/new.h \
backward/multiset.h backward/pair.h backward/iostream.h \
backward/rope.h backward/set.h backward/slist.h backward/stack.h \
backward/tempbuf.h backward/tree.h backward/vector.h \
backward/fstream.h backward/strstream.h backward/strstream
backward_headers = backward/complex.h backward/iomanip.h backward/istream.h backward/ostream.h backward/stream.h backward/streambuf.h backward/algo.h backward/algobase.h backward/alloc.h backward/bvector.h backward/defalloc.h backward/deque.h backward/function.h backward/hash_map.h backward/hash_set.h backward/hashtable.h backward/heap.h backward/iterator.h backward/list.h backward/map.h backward/multimap.h backward/new.h backward/multiset.h backward/pair.h backward/iostream.h backward/rope.h backward/set.h backward/slist.h backward/stack.h backward/tempbuf.h backward/tree.h backward/vector.h backward/fstream.h backward/strstream.h backward/strstream
ext_headers = \
ext/ropeimpl.h ext/stl_rope.h \
ext/stl_bvector.h ext/stl_hashtable.h ext/stl_hash_fun.h \
ext/hash_map ext/hash_set ext/rope ext/slist \
ext/tree ext/bvector
ext_headers = ext/ropeimpl.h ext/stl_rope.h ext/stl_bvector.h ext/stl_hashtable.h ext/stl_hash_fun.h ext/hash_map ext/hash_set ext/rope ext/slist ext/tree ext/bvector
c_base_headers = \
bits/std_cassert.h bits/std_cctype.h bits/std_cerrno.h \
bits/std_cfloat.h bits/std_climits.h bits/std_clocale.h \
bits/std_cmath.h bits/std_csetjmp.h bits/std_csignal.h \
bits/std_cstdarg.h bits/std_cstddef.h bits/std_cstdio.h \
bits/std_cstdlib.h bits/std_cstring.h bits/std_ctime.h \
bits/std_cwchar.h bits/std_cwctype.h bits/cmath.tcc
c_base_headers = bits/std_cassert.h bits/std_cctype.h bits/std_cerrno.h bits/std_cfloat.h bits/std_climits.h bits/std_clocale.h bits/std_cmath.h bits/std_csetjmp.h bits/std_csignal.h bits/std_cstdarg.h bits/std_cstddef.h bits/std_cstdio.h bits/std_cstdlib.h bits/std_cstring.h bits/std_ctime.h bits/std_cwchar.h bits/std_cwctype.h bits/cmath.tcc
@GLIBCPP_USE_CSHADOW_TRUE@c_shadow_headers = @GLIBCPP_USE_CSHADOW_TRUE@\
@GLIBCPP_USE_CSHADOW_TRUE@ assert.h ctype.h errno.h float.h limits.h locale.h math.h setjmp.h \
@GLIBCPP_USE_CSHADOW_TRUE@ signal.h stdarg.h stddef.h stdio.h stdlib.h string.h time.h wchar.h \
@GLIBCPP_USE_CSHADOW_TRUE@ wctype.h fcntl.h libio.h iolibio.h libioP.h pthread.h iconv.h \
@GLIBCPP_USE_CSHADOW_TRUE@ features.h langinfo.h \
@GLIBCPP_USE_CSHADOW_TRUE@ bits/wrap_libio.h bits/wrap_iolibio.h bits/wrap_libioP.h \
@GLIBCPP_USE_CSHADOW_TRUE@ bits/wrap_iconv.h bits/wrap_fcntl.h bits/wrap_pthread.h \
@GLIBCPP_USE_CSHADOW_TRUE@ bits/wrap_features.h bits/wrap_langinfo.h \
@GLIBCPP_USE_CSHADOW_TRUE@ sys/cdefs.h
@GLIBCPP_USE_CSHADOW_TRUE@c_shadow_headers = assert.h ctype.h errno.h float.h limits.h locale.h math.h setjmp.h signal.h stdarg.h stddef.h stdio.h stdlib.h string.h time.h wchar.h wctype.h fcntl.h libio.h iolibio.h libioP.h pthread.h iconv.h features.h langinfo.h bits/wrap_libio.h bits/wrap_iolibio.h bits/wrap_libioP.h bits/wrap_iconv.h bits/wrap_fcntl.h bits/wrap_pthread.h bits/wrap_features.h bits/wrap_langinfo.h sys/cdefs.h
@GLIBCPP_USE_CSHADOW_FALSE@c_shadow_headers =
std_headers = \
algorithm bitset complex deque fstream functional \
iomanip ios iosfwd iostream istream iterator limits list locale \
map memory numeric ostream queue set sstream stack stdexcept \
streambuf string utility valarray vector \
cassert cctype cerrno cfloat climits clocale ciso646 \
cmath csetjmp csignal cstdarg cstddef cstdio cstdlib \
cstring ctime cwchar cwctype
std_headers = algorithm bitset complex deque fstream functional iomanip ios iosfwd iostream istream iterator limits list locale map memory numeric ostream queue set sstream stack stdexcept streambuf string utility valarray vector cassert cctype cerrno cfloat climits clocale ciso646 cmath csetjmp csignal cstdarg cstddef cstdio cstdlib cstring ctime cwchar cwctype
@GLIBCPP_NEED_LIBIO_TRUE@libio_headers = @GLIBCPP_NEED_LIBIO_TRUE@\
@GLIBCPP_NEED_LIBIO_TRUE@ $(top_srcdir)/libio/_G_config.h $(top_srcdir)/libio/libio.h
@GLIBCPP_NEED_LIBIO_TRUE@libio_headers = $(top_srcdir)/libio/_G_config.h $(top_srcdir)/libio/libio.h
@GLIBCPP_NEED_LIBIO_FALSE@libio_headers =
build_headers = \
bits/std_limits.h \
bits/c++config.h bits/c++io.h bits/c++locale.h bits/c++threads.h \
bits/basic_file_model.h \
bits/atomicity.h bits/os_defines.h \
bits/ctype_base.h bits/ctype_noninline.h bits/ctype_inline.h
build_headers = bits/std_limits.h bits/c++config.h bits/c++io.h bits/c++locale.h bits/c++threads.h bits/basic_file_model.h bits/atomicity.h bits/os_defines.h bits/ctype_base.h bits/ctype_noninline.h bits/ctype_inline.h
sources = \
limitsMEMBERS.cc \
stdexcept.cc functexcept.cc bitset.cc \
globals.cc \
basic_file.cc ios.cc complex_io.cc strstream.cc \
c++locale.cc locale.cc localename.cc codecvt.cc \
locale-inst.cc stl-inst.cc misc-inst.cc valarray-inst.cc \
string-inst.cc wstring-inst.cc
sources = limitsMEMBERS.cc stdexcept.cc functexcept.cc bitset.cc globals.cc basic_file.cc ios.cc complex_io.cc strstream.cc c++locale.cc locale.cc localename.cc codecvt.cc locale-inst.cc stl-inst.cc misc-inst.cc valarray-inst.cc string-inst.cc wstring-inst.cc
VPATH = $(top_srcdir) $(top_srcdir)/src $(GLIBCPP_INCLUDE_DIR) $(GLIBCPP_INCLUDE_DIR)/std $(C_INCLUDE_DIR)
libstdc___la_SOURCES = $(sources)
libstdc___la_LIBADD = \
../libmath/libmath.la @libio_la@ \
../libsupc++/libsupc++convenience.la
libstdc___la_LIBADD = ../libmath/libmath.la @libio_la@ ../libsupc++/libsupc++convenience.la
libstdc___la_LDFLAGS = -version-info 3:0:0 -lm
libstdc___la_DEPENDENCIES = $(libstdc___la_LIBADD)
@GLIBCPP_USE_CSHADOW_TRUE@CSHADOW_H = @GLIBCPP_USE_CSHADOW_TRUE@$(top_builddir)/stamp-cshadow
@GLIBCPP_USE_CSHADOW_TRUE@CSHADOW_H = $(top_builddir)/stamp-cshadow
@GLIBCPP_USE_CSHADOW_FALSE@CSHADOW_H =
# Check for various configure bits that change where the headers get installed.
@ -283,12 +192,7 @@ c_incdir = @C_INCLUDE_DIR@
# set this option because CONFIG_CXXFLAGS has to be after
# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden
# as the occasion call for it. (ie, --enable-debug)
AM_CXXFLAGS = \
-fno-implicit-templates \
$(LIBSUPCXX_CXXFLAGS) \
$(WARN_CXXFLAGS) \
$(OPTIMIZE_CXXFLAGS) \
$(CONFIG_CXXFLAGS)
AM_CXXFLAGS = -fno-implicit-templates $(LIBSUPCXX_CXXFLAGS) $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
# libstdc++ libtool notes
@ -309,8 +213,7 @@ AM_CXXFLAGS = \
# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe
# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to
# attempt to infer which configuration to use
LTCXXCOMPILE = $(LIBTOOL) --tag CXX --mode=compile $(CXX) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(AM_CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) --tag CXX --mode=compile $(CXX) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(AM_CXXFLAGS)
# 3) We'd have a problem when building the shared libstdc++ object if
@ -319,8 +222,7 @@ LTCXXCOMPILE = $(LIBTOOL) --tag CXX --mode=compile $(CXX) $(INCLUDES) \
# course is problematic at this point. So, we get the top-level
# directory to configure libstdc++-v3 to use gcc as the C++
# compilation driver.
CXXLINK = $(LIBTOOL) --tag CXX --mode=link $(CXX) \
@OPT_LDFLAGS@ @SECTION_LDFLAGS@ $(AM_CXXFLAGS) $(LDFLAGS) -o $@
CXXLINK = $(LIBTOOL) --tag CXX --mode=link $(CXX) @OPT_LDFLAGS@ @SECTION_LDFLAGS@ $(AM_CXXFLAGS) $(LDFLAGS) -o $@
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
@ -475,7 +377,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
if test -f $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \