diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 48 | ||||
-rw-r--r-- | gcc/Makefile.in | 9 | ||||
-rw-r--r-- | gcc/ada/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/ada/misc.c | 1 | ||||
-rw-r--r-- | gcc/c-decl.c | 1 | ||||
-rw-r--r-- | gcc/config/arm/arm-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 297 | ||||
-rw-r--r-- | gcc/config/arm/arm.h | 12 | ||||
-rw-r--r-- | gcc/config/arm/bpabi.h | 3 | ||||
-rw-r--r-- | gcc/config/arm/elf.h | 2 | ||||
-rw-r--r-- | gcc/config/arm/lib1funcs.asm | 1 | ||||
-rw-r--r-- | gcc/config/arm/libgcc-bpabi.ver | 14 | ||||
-rw-r--r-- | gcc/config/arm/t-bpabi | 8 | ||||
-rw-r--r-- | gcc/config/arm/t-symbian | 5 | ||||
-rw-r--r-- | gcc/config/i386/t-netware | 1 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.h | 2 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 2 | ||||
-rw-r--r-- | gcc/cp/except.c | 5 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 19 | ||||
-rw-r--r-- | gcc/except.c | 134 | ||||
-rw-r--r-- | gcc/except.h | 1 | ||||
-rw-r--r-- | gcc/java/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/java/decl.c | 1 | ||||
-rw-r--r-- | gcc/objc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 1 | ||||
-rw-r--r-- | gcc/optabs.c | 3 | ||||
-rw-r--r-- | gcc/opts.c | 7 | ||||
-rw-r--r-- | gcc/target-def.h | 14 | ||||
-rw-r--r-- | gcc/target.h | 11 | ||||
-rw-r--r-- | gcc/unwind-c.c | 46 |
31 files changed, 609 insertions, 62 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 29c1e4f..81a3106 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,51 @@ +2005-06-28 Paul Brook <paul@codesourcery.com> + + * Makefile.in: Set and use UNWIND_H. Install as unwind.h. + * c-decl.c (finish_decl): Call default_init_unwind_resume_libfunc. + * except.c (add_ehspec_entry): Generate arm eabi filter lists. + (assign_filter_values): Ditto. + (output_ttype): New function. + (output_function_exception_table): Use output_ttype. Generate arm + eabi filter lists. + (default_init_unwind_resume_libfunc): New function. + * except.h (default_init_unwind_resume_libfunc): Add prototype. + * optabs.c (init_optabs): Don't set unwind_resume_libfunc. + * opts.c (decode_options): Use targetm.unwind_tables_default. + * target-def.h (TARGET_ASM_TTYPE): Provide and use definition. + (TARGET_ARM_EABI_UNWINDER, TARGET_UNWIND_TABLES_DEFAULT): Ditto. + * target.h (struct gcc_target): Add asm.ttype, unwind_tables_default + and arm_eabi_unwinder. + * unwind-c.c: Support Arm EABI unwinder. + * unwind.h: Rename ... + * unwind-generic.h: ... To this. + * doc/tm.texi (TARGET_ASM_TTYPE, TARGET_ARM_EABI_UNWINDER): Document. + (TARGET_UNWID_TABLES_DEFAULT): Document. + + * config/arm/arm-protos.h (arm_output_fn_unwind): Add prototype. + * config/arm/arm.c (arm_unwind_emit, arm_output_ttype): New functions. + (TARGET_UNWIND_EMIT, TARGET_ASM_TTYPE, TARGET_ARM_EABI_UNWINDER): + Define. + (thumb_pushpop, thumb_output_function_prologue): Output unwinding + directives. + (arm_unwind_emit_stm, arm_unwind_emit_set): New functions. + * config/arm/arm.h (MUST_USE_SJLJ_EXCEPTIONS): Only define when + !TARGET_UNWIND_INFO. + (ARM_OUTPUT_FN_UNWIND, ARM_EABI_UNWIND_TABLES): Define. + * config/arm/bpabi.h (TARGET_UNWIND_INFO): Define. + * config/arm/elf.h (ASM_DECLARE_FUNCTION_NAME, + ASM_DECLARE_FUNCTION_SIZE): Use ARM_OUTPUT_FN_UNWIND. + * config/arm/lib1funcs.asm: Include libunwind.S. + * config/arm/libgcc-bpabi.ver: Add unwinding routines. + * config/arm/libunwind.S: New file. + * config/arm/pr-support.c: New file. + * config/arm/t-bpabi (LIB1ASMFUNCS): Add _unwind. + (UNWIND_H, LIB2ADDEH, LIB2ADDEHDEP): Set. + * config/arm/t-symbian (UNWIND_H, LIB2ADDEH, LIB2ADDEHDEP): Set. + * config/arm/unwind-arm.c: New file. + * config/arm/unwind-arm.h: New file. + * config/i386/t-netware (USER_H): Remove unwind.h. + * config/ia64/ia64.h (TARGET_UNWIND_TABLES_DEFAULT): Define. + 2005-06-28 DJ Delorie <dj@redhat.com> * c-decl.c (pop_scope): Move warning control into warning call. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 98ace16..3ff5c94 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -313,9 +313,10 @@ USER_H = $(srcdir)/ginclude/float.h \ $(srcdir)/ginclude/stdbool.h \ $(srcdir)/ginclude/stddef.h \ $(srcdir)/ginclude/varargs.h \ - $(srcdir)/unwind.h \ $(EXTRA_HEADERS) +UNWIND_H = $(srcdir)/unwind-generic.h + # The GCC to use for compiling libgcc.a and crt*.o. # Usually the one we just built. # Don't use this as a dependency--use $(GCC_PASSES) or $(GCC_PARTS). @@ -534,7 +535,7 @@ LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \ $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c LIB2ADDEHSTATIC = $(LIB2ADDEH) LIB2ADDEHSHARED = $(LIB2ADDEH) -LIB2ADDEHDEP = unwind.h unwind-pe.h unwind.inc unwind-dw2-fde.h unwind-dw2.h +LIB2ADDEHDEP = $(UNWIND_H) unwind-pe.h unwind.inc unwind-dw2-fde.h unwind-dw2.h # Don't build libunwind by default. LIBUNWIND = @@ -3034,7 +3035,7 @@ gcov-dump$(exeext): $(GCOV_DUMP_OBJS) $(LIBDEPS) # be rebuilt. # Build the include directory -stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h +stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h $(UNWIND_H) # Copy in the headers provided with gcc. # The sed command gets just the last file name component; # this is necessary because VPATH could add a dirname. @@ -3052,6 +3053,7 @@ stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h done rm -f include/limits.h cp xlimits.h include/limits.h + cp $(UNWIND_H) include/unwind.h chmod a+r include/limits.h # Install the README rm -f include/README @@ -3684,6 +3686,7 @@ install-mkheaders: stmp-int-hdrs $(STMP_FIXPROTO) install-itoolsdirs \ $(DESTDIR)$(itoolsdatadir)/include/$$realfile ; \ done $(INSTALL_DATA) xlimits.h $(DESTDIR)$(itoolsdatadir)/include/limits.h + $(INSTALL_DATA) $(UNWIND_H) $(DESTDIR)$(itoolsdatadir)/include/unwind.h $(INSTALL_DATA) $(srcdir)/gsyslimits.h \ $(DESTDIR)$(itoolsdatadir)/gsyslimits.h $(INSTALL_DATA) macro_list $(DESTDIR)$(itoolsdatadir)/macro_list diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 0e6b95d..18b366b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2005-06-28 Paul Brook <paul@codesourcery.com> + + * misc.c (gnat_init_gcc_eh): Call default_init_unwind_resume_libfunc. + 2005-06-14 Olivier Hainque <hainque@adacore.com> Eric Botcazou <ebotcazou@adacore.com> diff --git a/gcc/ada/misc.c b/gcc/ada/misc.c index a993bc1..544419d 100644 --- a/gcc/ada/misc.c +++ b/gcc/ada/misc.c @@ -462,6 +462,7 @@ gnat_init_gcc_eh (void) using_eh_for_cleanups (); eh_personality_libfunc = init_one_libfunc ("__gnat_eh_personality"); + default_init_unwind_resume_libfunc (); lang_eh_type_covers = gnat_eh_type_covers; lang_eh_runtime_type = gnat_eh_runtime_type; diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 728383f..eececb1 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -3537,6 +3537,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree) = init_one_libfunc (USING_SJLJ_EXCEPTIONS ? "__gcc_personality_sj0" : "__gcc_personality_v0"); + default_init_unwind_resume_libfunc (); using_eh_for_cleanups (); } diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 352a289..b15fe10 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -39,6 +39,8 @@ extern HOST_WIDE_INT arm_compute_initial_elimination_offset (unsigned int, extern HOST_WIDE_INT thumb_compute_initial_elimination_offset (unsigned int, unsigned int); extern unsigned int arm_dbx_register_number (unsigned int); +extern void arm_output_fn_unwind (FILE *, bool); + #ifdef TREE_CODE extern int arm_return_in_memory (tree); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 5348c79..4e17d3a 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -171,6 +171,10 @@ static bool arm_default_short_enums (void); static bool arm_align_anon_bitfield (void); static bool arm_return_in_msb (tree); static bool arm_must_pass_in_stack (enum machine_mode, tree); +#ifdef TARGET_UNWIND_INFO +static void arm_unwind_emit (FILE *, rtx); +static bool arm_output_ttype (rtx); +#endif static tree arm_cxx_guard_type (void); static bool arm_cxx_guard_mask_bit (void); @@ -337,6 +341,18 @@ static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode); #undef TARGET_MUST_PASS_IN_STACK #define TARGET_MUST_PASS_IN_STACK arm_must_pass_in_stack +#ifdef TARGET_UNWIND_INFO +#undef TARGET_UNWIND_EMIT +#define TARGET_UNWIND_EMIT arm_unwind_emit + +/* EABI unwinding tables use a different format for the typeinfo tables. */ +#undef TARGET_ASM_TTYPE +#define TARGET_ASM_TTYPE arm_output_ttype + +#undef TARGET_ARM_EABI_UNWINDER +#define TARGET_ARM_EABI_UNWINDER true +#endif /* TARGET_UNWIND_INFO */ + struct gcc_target targetm = TARGET_INITIALIZER; /* Obstack for minipool constant handling. */ @@ -12417,6 +12433,21 @@ thumb_pushpop (FILE *f, unsigned long mask, int push, int *cfa_offset, return; } + if (ARM_EABI_UNWIND_TABLES && push) + { + fprintf (f, "\t.save\t{"); + for (regno = 0; regno < 15; regno++) + { + if (real_regs & (1 << regno)) + { + if (real_regs & ((1 << regno) -1)) + fprintf (f, ", "); + asm_fprintf (f, "%r", regno); + } + } + fprintf (f, "}\n"); + } + fprintf (f, "\t%s\t{", push ? "push" : "pop"); /* Look at the low registers first. */ @@ -13370,6 +13401,11 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED) if (current_function_pretend_args_size) { + /* Output unwind directive for the stack adjustment. */ + if (ARM_EABI_UNWIND_TABLES) + fprintf (f, "\t.pad #%d\n", + current_function_pretend_args_size); + if (cfun->machine->uses_anonymous_args) { int num_pushes; @@ -13435,6 +13471,9 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED) work_register = thumb_find_work_register (live_regs_mask); + if (ARM_EABI_UNWIND_TABLES) + asm_fprintf (f, "\t.pad #16\n"); + asm_fprintf (f, "\tsub\t%r, %r, #16\t%@ Create stack backtrace structure\n", SP_REGNUM, SP_REGNUM); @@ -14662,3 +14701,261 @@ arm_dbx_register_number (unsigned int regno) gcc_unreachable (); } + +#ifdef TARGET_UNWIND_INFO +/* Emit unwind directives for a store-multiple instruction. This should + only ever be generated by the function prologue code, so we expect it + to have a particular form. */ + +static void +arm_unwind_emit_stm (FILE * asm_out_file, rtx p) +{ + int i; + HOST_WIDE_INT offset; + HOST_WIDE_INT nregs; + int reg_size; + unsigned reg; + unsigned lastreg; + rtx e; + + /* First insn will adjust the stack pointer. */ + e = XVECEXP (p, 0, 0); + if (GET_CODE (e) != SET + || GET_CODE (XEXP (e, 0)) != REG + || REGNO (XEXP (e, 0)) != SP_REGNUM + || GET_CODE (XEXP (e, 1)) != PLUS) + abort (); + + offset = -INTVAL (XEXP (XEXP (e, 1), 1)); + nregs = XVECLEN (p, 0) - 1; + + reg = REGNO (XEXP (XVECEXP (p, 0, 1), 1)); + if (reg < 16) + { + /* The function prologue may also push pc, but not annotate it as it is + never restored. We turn this into an stack pointer adjustment. */ + if (nregs * 4 == offset - 4) + { + fprintf (asm_out_file, "\t.pad #4\n"); + offset -= 4; + } + reg_size = 4; + } + else if (IS_VFP_REGNUM (reg)) + { + /* FPA register saves use an additional word. */ + offset -= 4; + reg_size = 8; + } + else if (reg >= FIRST_FPA_REGNUM && reg <= LAST_FPA_REGNUM) + { + /* FPA registers are done differently. */ + asm_fprintf (asm_out_file, "\t.save %r, %d\n", reg, nregs); + return; + } + else + /* Unknown register type. */ + abort (); + + /* If the stack increment doesn't match the size of the saved registers, + something has gone horribly wrong. */ + if (offset != nregs * reg_size) + abort (); + + fprintf (asm_out_file, "\t.save {"); + + offset = 0; + lastreg = 0; + /* The remaining insns will describe the stores. */ + for (i = 1; i <= nregs; i++) + { + /* Expect (set (mem <addr>) (reg)). + Where <addr> is (reg:SP) or (plus (reg:SP) (const_int)). */ + e = XVECEXP (p, 0, i); + if (GET_CODE (e) != SET + || GET_CODE (XEXP (e, 0)) != MEM + || GET_CODE (XEXP (e, 1)) != REG) + abort (); + + reg = REGNO (XEXP (e, 1)); + if (reg < lastreg) + abort (); + + if (i != 1) + fprintf (asm_out_file, ", "); + /* We can't use %r for vfp because we need to use the + double precision register names. */ + if (IS_VFP_REGNUM (reg)) + asm_fprintf (asm_out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2); + else + asm_fprintf (asm_out_file, "%r", reg); + +#ifdef ENABLE_CHECKING + /* Check that the addresses are consecutive. */ + e = XEXP (XEXP (e, 0), 0); + if (GET_CODE (e) == PLUS) + { + offset += reg_size; + if (GET_CODE (XEXP (e, 0)) != REG + || REGNO (XEXP (e, 0)) != SP_REGNUM + || GET_CODE (XEXP (e, 1)) != CONST_INT + || offset != INTVAL (XEXP (e, 1))) + abort (); + } + else if (i != 1 + || GET_CODE (e) != REG + || REGNO (e) != SP_REGNUM) + abort (); +#endif + } + fprintf (asm_out_file, "}\n"); +} + +/* Emit unwind directives for a SET. */ + +static void +arm_unwind_emit_set (FILE * asm_out_file, rtx p) +{ + rtx e0; + rtx e1; + + e0 = XEXP (p, 0); + e1 = XEXP (p, 1); + switch (GET_CODE (e0)) + { + case MEM: + /* Pushing a single register. */ + if (GET_CODE (XEXP (e0, 0)) != PRE_DEC + || GET_CODE (XEXP (XEXP (e0, 0), 0)) != REG + || REGNO (XEXP (XEXP (e0, 0), 0)) != SP_REGNUM) + abort (); + + asm_fprintf (asm_out_file, "\t.save "); + if (IS_VFP_REGNUM (REGNO (e1))) + asm_fprintf(asm_out_file, "{d%d}\n", + (REGNO (e1) - FIRST_VFP_REGNUM) / 2); + else + asm_fprintf(asm_out_file, "{%r}\n", REGNO (e1)); + break; + + case REG: + if (REGNO (e0) == SP_REGNUM) + { + /* A stack increment. */ + if (GET_CODE (e1) != PLUS + || GET_CODE (XEXP (e1, 0)) != REG + || REGNO (XEXP (e1, 0)) != SP_REGNUM + || GET_CODE (XEXP (e1, 1)) != CONST_INT) + abort (); + + asm_fprintf (asm_out_file, "\t.pad #%d\n", + -INTVAL (XEXP (e1, 1))); + } + else if (REGNO (e0) == HARD_FRAME_POINTER_REGNUM) + { + HOST_WIDE_INT offset; + unsigned reg; + + if (GET_CODE (e1) == PLUS) + { + if (GET_CODE (XEXP (e1, 0)) != REG + || GET_CODE (XEXP (e1, 1)) != CONST_INT) + abort (); + reg = REGNO (XEXP (e1, 0)); + offset = INTVAL (XEXP (e1, 1)); + asm_fprintf (asm_out_file, "\t.setfp %r, %r, #%d\n", + HARD_FRAME_POINTER_REGNUM, reg, + INTVAL (XEXP (e1, 1))); + } + else if (GET_CODE (e1) == REG) + { + reg = REGNO (e1); + asm_fprintf (asm_out_file, "\t.setfp %r, %r\n", + HARD_FRAME_POINTER_REGNUM, reg); + } + else + abort (); + } + else if (GET_CODE (e1) == REG && REGNO (e1) == SP_REGNUM) + { + /* Move from sp to reg. */ + asm_fprintf (asm_out_file, "\t.movsp %r\n", REGNO (e0)); + } + else + abort (); + break; + + default: + abort (); + } +} + + +/* Emit unwind directives for the given insn. */ + +static void +arm_unwind_emit (FILE * asm_out_file, rtx insn) +{ + rtx pat; + + if (!ARM_EABI_UNWIND_TABLES) + return; + + if (GET_CODE (insn) == NOTE || !RTX_FRAME_RELATED_P (insn)) + return; + + pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); + if (pat) + pat = XEXP (pat, 0); + else + pat = PATTERN (insn); + + switch (GET_CODE (pat)) + { + case SET: + arm_unwind_emit_set (asm_out_file, pat); + break; + + case SEQUENCE: + /* Store multiple. */ + arm_unwind_emit_stm (asm_out_file, pat); + break; + + default: + abort(); + } +} + + +/* Output a reference from a function exception table to the type_info + object X. The EABI specifies that the symbol should be relocated by + an R_ARM_TARGET2 relocation. */ + +static bool +arm_output_ttype (rtx x) +{ + fputs ("\t.word\t", asm_out_file); + output_addr_const (asm_out_file, x); + /* Use special relocations for symbol references. */ + if (GET_CODE (x) != CONST_INT) + fputs ("(TARGET2)", asm_out_file); + fputc ('\n', asm_out_file); + + return TRUE; +} +#endif /* TARGET_UNWIND_INFO */ + + +/* Output unwind directives for the start/end of a function. */ + +void +arm_output_fn_unwind (FILE * f, bool prologue) +{ + if (!ARM_EABI_UNWIND_TABLES) + return; + + if (prologue) + fputs ("\t.fnstart\n", f); + else + fputs ("\t.fnend\n", f); +} diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 65b4bad..327393c 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -770,8 +770,11 @@ extern int arm_structure_size_boundary; #define FIRST_HI_REGNUM 8 #define LAST_HI_REGNUM 11 +#ifndef TARGET_UNWIND_INFO /* We use sjlj exceptions for backwards compatibility. */ #define MUST_USE_SJLJ_EXCEPTIONS 1 +#endif + /* We can generate DWARF2 Unwind info, even though we don't use it. */ #define DWARF2_UNWIND_INFO 1 @@ -1977,6 +1980,15 @@ typedef struct if (!TARGET_LONG_CALLS || ! DECL_SECTION_NAME (DECL)) \ arm_encode_call_attribute (DECL, SHORT_CALL_FLAG_CHAR) +#define ARM_OUTPUT_FN_UNWIND(F, PROLOGUE) arm_output_fn_unwind (F, PROLOGUE) + +#ifdef TARGET_UNWIND_INFO +#define ARM_EABI_UNWIND_TABLES \ + ((!USING_SJLJ_EXCEPTIONS && flag_exceptions) || flag_unwind_tables) +#else +#define ARM_EABI_UNWIND_TABLES 0 +#endif + /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check its validity for a certain class. We have two alternate definitions for each of them. diff --git a/gcc/config/arm/bpabi.h b/gcc/config/arm/bpabi.h index 981c58c..7fb7d6a 100644 --- a/gcc/config/arm/bpabi.h +++ b/gcc/config/arm/bpabi.h @@ -26,6 +26,9 @@ /* Assume that AAPCS ABIs should adhere to the full BPABI. */ #define TARGET_BPABI (TARGET_AAPCS_BASED) +/* BPABI targets use EABI frame unwinding tables. */ +#define TARGET_UNWIND_INFO 1 + /* Section 4.1 of the AAPCS requires the use of VFP format. */ #define FPUTYPE_DEFAULT FPUTYPE_VFP diff --git a/gcc/config/arm/elf.h b/gcc/config/arm/elf.h index a560021..ae3d533 100644 --- a/gcc/config/arm/elf.h +++ b/gcc/config/arm/elf.h @@ -77,6 +77,7 @@ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \ ASM_OUTPUT_LABEL(FILE, NAME); \ + ARM_OUTPUT_FN_UNWIND (FILE, TRUE); \ } \ while (0) @@ -85,6 +86,7 @@ #define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ do \ { \ + ARM_OUTPUT_FN_UNWIND (FILE, FALSE); \ ARM_DECLARE_FUNCTION_SIZE (FILE, FNAME, DECL); \ if (!flag_inhibit_size_directive) \ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \ diff --git a/gcc/config/arm/lib1funcs.asm b/gcc/config/arm/lib1funcs.asm index 519b41e..ebf31eb 100644 --- a/gcc/config/arm/lib1funcs.asm +++ b/gcc/config/arm/lib1funcs.asm @@ -1309,4 +1309,5 @@ LSYM(Lchange_\register): #include "ieee754-df.S" #include "ieee754-sf.S" #include "bpabi.S" +#include "libunwind.S" #endif /* __symbian__ */ diff --git a/gcc/config/arm/libgcc-bpabi.ver b/gcc/config/arm/libgcc-bpabi.ver index 788e3ad..35966bb 100644 --- a/gcc/config/arm/libgcc-bpabi.ver +++ b/gcc/config/arm/libgcc-bpabi.ver @@ -60,4 +60,18 @@ GCC_3.5 { __aeabi_ulcmp __aeabi_ul2d __aeabi_ul2f + + # Exception-Handling + # \S 7.5 + _Unwind_Complete + _Unwind_VRS_Get + _Unwind_VRS_Set + _Unwind_VRS_Pop + # \S 9.2 + __aeabi_unwind_cpp_pr0 + __aeabi_unwind_cpp_pr1 + __aeabi_unwind_cpp_pr2 + # The libstdc++ exception-handling personality routine uses this + # GNU-specific entry point. + __gnu_unwind_frame } diff --git a/gcc/config/arm/t-bpabi b/gcc/config/arm/t-bpabi index 74445dd..74c0ae1 100644 --- a/gcc/config/arm/t-bpabi +++ b/gcc/config/arm/t-bpabi @@ -1,9 +1,15 @@ # Add the bpabi.S functions. -LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod +LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod \ + _unwind # Add the BPABI C functions. LIB2FUNCS_EXTRA = $(srcdir)/config/arm/bpabi.c +UNWIND_H = $(srcdir)/config/arm/unwind-arm.h +LIB2ADDEH = $(srcdir)/config/arm/unwind-arm.c \ + $(srcdir)/config/arm/pr-support.c $(srcdir)/unwind-c.c +LIB2ADDEHDEP = $(UNWIND_H) + # Add the BPABI names. SHLIB_MAPFILES += $(srcdir)/config/arm/libgcc-bpabi.ver diff --git a/gcc/config/arm/t-symbian b/gcc/config/arm/t-symbian index 34a58ce..8f72b3e 100644 --- a/gcc/config/arm/t-symbian +++ b/gcc/config/arm/t-symbian @@ -12,6 +12,11 @@ LIB1ASMFUNCS += \ _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \ _fixsfsi _fixunssfsi +# Include the gcc personality routine +UNWIND_H = $(srcdir)/config/arm/unwind-arm.h +LIB2ADDEH = $(srcdir)/unwind-c.c +LIB2ADDEHDEP = $(UNWIND_H) + # Create a multilib for processors with VFP floating-point, and a # multilib for those without -- using the soft-float ABI in both # cases. Symbian OS object should be compiled with interworking diff --git a/gcc/config/i386/t-netware b/gcc/config/i386/t-netware index cc229b8..2d3a828 100644 --- a/gcc/config/i386/t-netware +++ b/gcc/config/i386/t-netware @@ -6,5 +6,4 @@ netware.o: $(srcdir)/config/i386/netware.c $(RTL_H) $(TREE_H) $(CONFIG_H) $(TM_P # We don't need some of GCC's own include files. USER_H = $(srcdir)/ginclude/stdarg.h \ $(srcdir)/ginclude/varargs.h \ - $(srcdir)/unwind.h \ $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS) diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index e97bf07..9e52773 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -1985,6 +1985,8 @@ extern int ia64_final_schedule; #define TARGET_UNWIND_INFO 1 +#define TARGET_UNWIND_TABLES_DEFAULT true + #define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 15 : INVALID_REGNUM) /* This function contains machine specific function data. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d22990e..128ea64 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2005-06-28 Paul Brook <paul@codesourcery.com> + + * Make-lang.in (cp/except.o): Depend on $(TARGET_H) + * except.c: Include target.h. + (init_exception_processing): Initialize unwind_resume_libfunc. + * doc/tm.texi: Document TARGET_ASM_TTYPE + 2005-06-26 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> * call.c (build_over_call): Pass in named argument list to diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 6adedec..f555f31 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -272,7 +272,7 @@ cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(TM_H) cp/rtti.o: cp/rtti.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h convert.h \ gt-cp-rtti.h cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) except.h \ - toplev.h cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h + toplev.h cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h $(TARGET_H) cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(RTL_H) flags.h $(EXPR_H) \ toplev.h except.h $(TM_P_H) cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/cp-objcp-common.h \ diff --git a/gcc/cp/except.c b/gcc/cp/except.c index de83bba..be7208e 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -38,6 +38,7 @@ Boston, MA 02110-1301, USA. */ #include "toplev.h" #include "tree-inline.h" #include "tree-iterator.h" +#include "target.h" static void push_eh_cleanup (tree); static tree prepare_eh_type (tree); @@ -79,6 +80,10 @@ init_exception_processing (void) eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS ? "__gxx_personality_sj0" : "__gxx_personality_v0"); + if (targetm.arm_eabi_unwinder) + unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup"); + else + default_init_unwind_resume_libfunc (); lang_eh_runtime_type = build_eh_type_type; lang_protect_cleanup_actions = &cp_protect_cleanup_actions; diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index cd2bf87..bbca6b9 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -7648,6 +7648,11 @@ Define this macro if your target has ABI specified unwind tables. Usually these will be output by @code{TARGET_UNWIND_EMIT}. @end defmac +@deftypevar {Target Hook} bool TARGET_UNWID_TABLES_DEFAULT +This variable should be set to @code{true} if the target ABI requires unwinding +tables even when exceptions are not used. +@end deftypevar + @defmac MUST_USE_SJLJ_EXCEPTIONS This macro need only be defined if @code{DWARF2_UNWIND_INFO} is runtime-variable. In that case, @file{except.h} cannot correctly @@ -7698,6 +7703,20 @@ register in Dwarf. Otherwise, this hook should return @code{NULL_RTX}. If not defined, the default is to return @code{NULL_RTX}. @end deftypefn +@deftypefn {Target Hook} bool TARGET_ASM_TTYPE (rtx @var{sym}) +This hook is used to output a reference from a frame unwinding table to +the type_info object identified by @var{sym}. It should return @code{true} +if the reference was output. Returning @code{false} will cause the +reference to be output using the normal Dwarf2 routines. +@end deftypefn + +@deftypefn {Target Hook} bool TARGET_ARM_EABI_UNWINDER +This hook should be set to @code{true} on targets that use an ARM EABI +based unwinding library, and @code{false} on other targets. This effects +the format of unwinding tables, and how the unwinder in entered after +running a cleanup. The default is @code{false}. +@end deftypefn + @node Alignment Output @subsection Assembler Commands for Alignment diff --git a/gcc/except.c b/gcc/except.c index 3c42910..1bcdc28 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -1134,12 +1134,23 @@ add_ehspec_entry (htab_t ehspec_hash, htab_t ttypes_hash, tree list) n->filter = -(VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data) + 1); *slot = n; - /* Look up each type in the list and encode its filter - value as a uleb128. Terminate the list with 0. */ + /* Generate a 0 terminated list of filter values. */ for (; list ; list = TREE_CHAIN (list)) - push_uleb128 (&cfun->eh->ehspec_data, - add_ttypes_entry (ttypes_hash, TREE_VALUE (list))); - VARRAY_PUSH_UCHAR (cfun->eh->ehspec_data, 0); + { + if (targetm.arm_eabi_unwinder) + VARRAY_PUSH_TREE (cfun->eh->ehspec_data, TREE_VALUE (list)); + else + { + /* Look up each type in the list and encode its filter + value as a uleb128. */ + push_uleb128 (&cfun->eh->ehspec_data, + add_ttypes_entry (ttypes_hash, TREE_VALUE (list))); + } + } + if (targetm.arm_eabi_unwinder) + VARRAY_PUSH_TREE (cfun->eh->ehspec_data, NULL_TREE); + else + VARRAY_PUSH_UCHAR (cfun->eh->ehspec_data, 0); } return n->filter; @@ -1157,7 +1168,10 @@ assign_filter_values (void) htab_t ttypes, ehspec; cfun->eh->ttype_data = VEC_alloc (tree, gc, 16); - VARRAY_UCHAR_INIT (cfun->eh->ehspec_data, 64, "ehspec_data"); + if (targetm.arm_eabi_unwinder) + VARRAY_TREE_INIT (cfun->eh->ehspec_data, 64, "ehspec_data"); + else + VARRAY_UCHAR_INIT (cfun->eh->ehspec_data, 64, "ehspec_data"); ttypes = htab_create (31, ttypes_filter_hash, ttypes_filter_eq, free); ehspec = htab_create (31, ehspec_filter_hash, ehspec_filter_eq, free); @@ -3377,6 +3391,54 @@ default_exception_section (void) readonly_data_section (); } + +/* Output a reference from an exception table to the type_info object TYPE. + TT_FORMAT and TT_FORMAT_SIZE descibe the DWARF encoding method used for + the value. */ + +static void +output_ttype (tree type, int tt_format, int tt_format_size) +{ + rtx value; + + if (type == NULL_TREE) + value = const0_rtx; + else + { + struct cgraph_varpool_node *node; + + type = lookup_type_for_runtime (type); + value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER); + + /* Let cgraph know that the rtti decl is used. Not all of the + paths below go through assemble_integer, which would take + care of this for us. */ + STRIP_NOPS (type); + if (TREE_CODE (type) == ADDR_EXPR) + { + type = TREE_OPERAND (type, 0); + if (TREE_CODE (type) == VAR_DECL) + { + node = cgraph_varpool_node (type); + if (node) + cgraph_varpool_mark_needed_node (node); + } + } + else if (TREE_CODE (type) != INTEGER_CST) + abort (); + } + + /* Allow the target to override the type table entry format. */ + if (targetm.asm_out.ttype (value)) + return; + + if (tt_format == DW_EH_PE_absptr || tt_format == DW_EH_PE_aligned) + assemble_integer (value, tt_format_size, + tt_format_size * BITS_PER_UNIT, 1); + else + dw2_asm_output_encoded_addr_rtx (tt_format, value, NULL); +} + void output_function_exception_table (void) { @@ -3536,40 +3598,7 @@ output_function_exception_table (void) while (i-- > 0) { tree type = VEC_index (tree, cfun->eh->ttype_data, i); - rtx value; - - if (type == NULL_TREE) - value = const0_rtx; - else - { - struct cgraph_varpool_node *node; - - type = lookup_type_for_runtime (type); - value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER); - - /* Let cgraph know that the rtti decl is used. Not all of the - paths below go through assemble_integer, which would take - care of this for us. */ - STRIP_NOPS (type); - if (TREE_CODE (type) == ADDR_EXPR) - { - type = TREE_OPERAND (type, 0); - if (TREE_CODE (type) == VAR_DECL) - { - node = cgraph_varpool_node (type); - if (node) - cgraph_varpool_mark_needed_node (node); - } - } - else - gcc_assert (TREE_CODE (type) == INTEGER_CST); - } - - if (tt_format == DW_EH_PE_absptr || tt_format == DW_EH_PE_aligned) - assemble_integer (value, tt_format_size, - tt_format_size * BITS_PER_UNIT, 1); - else - dw2_asm_output_encoded_addr_rtx (tt_format, value, NULL); + output_ttype (type, tt_format, tt_format_size); } #ifdef HAVE_AS_LEB128 @@ -3580,8 +3609,16 @@ output_function_exception_table (void) /* ??? Decode and interpret the data for flag_debug_asm. */ n = VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data); for (i = 0; i < n; ++i) - dw2_asm_output_data (1, VARRAY_UCHAR (cfun->eh->ehspec_data, i), - (i ? NULL : "Exception specification table")); + { + if (targetm.arm_eabi_unwinder) + { + tree type = VARRAY_TREE (cfun->eh->ehspec_data, i); + output_ttype (type, tt_format, tt_format_size); + } + else + dw2_asm_output_data (1, VARRAY_UCHAR (cfun->eh->ehspec_data, i), + (i ? NULL : "Exception specification table")); + } current_function_section (current_function_decl); } @@ -3730,4 +3767,17 @@ verify_eh_tree (struct function *fun) } } } + + +/* Initialize unwind_resume_libfunc. */ + +void +default_init_unwind_resume_libfunc (void) +{ + /* The default c++ routines aren't actually c++ specific, so use those. */ + unwind_resume_libfunc = + init_one_libfunc ( USING_SJLJ_EXCEPTIONS ? "_Unwind_SjLj_Resume" + : "_Unwind_Resume"); +} + #include "gt-except.h" diff --git a/gcc/except.h b/gcc/except.h index 72073c0..d5e391d 100644 --- a/gcc/except.h +++ b/gcc/except.h @@ -85,6 +85,7 @@ typedef tree (*duplicate_eh_regions_map) (tree, void *); extern int duplicate_eh_regions (struct function *, duplicate_eh_regions_map, void *, int); extern void sjlj_emit_function_exit_after (rtx); +extern void default_init_unwind_resume_libfunc (void); extern struct eh_region *gen_eh_region_cleanup (struct eh_region *, struct eh_region *); diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 239e2b7..68699ff 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,8 @@ +2005-06-28 Paul Brook <paul@codesourcery.com> + + * decl.c (java_init_decl_processing): Call + default_init_unwind_resume_libfunc. + 2005-06-27 Tom Tromey <tromey@redhat.com> PR java/21540, PR java/13788: diff --git a/gcc/java/decl.c b/gcc/java/decl.c index b869016..e63ef84 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -1197,6 +1197,7 @@ java_init_decl_processing (void) eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS ? "__gcj_personality_sj0" : "__gcj_personality_v0"); + default_init_unwind_resume_libfunc (); lang_eh_runtime_type = do_nothing; diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 57a326a..52325f4 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,8 @@ +2005-06-28 Paul Brook <paul@codesourcery.com> + + * objc-act.c (objc_init_exceptions): Call + default_init_unwind_resume_libfunc. + 2005-06-27 Ziemowit Laski <zlaski@apple.com> * objc-act.c (objc_build_struct): Save the TYPE_OBJC_INFO diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 35951fe..d4c20a8 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -3407,6 +3407,7 @@ objc_init_exceptions (void) = init_one_libfunc (USING_SJLJ_EXCEPTIONS ? "__gnu_objc_personality_sj0" : "__gnu_objc_personality_v0"); + default_init_unwind_resume_libfunc (); using_eh_for_cleanups (); lang_eh_runtime_type = objc_eh_runtime_type; } diff --git a/gcc/optabs.c b/gcc/optabs.c index 1fb1136..6f5716e 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -5288,9 +5288,6 @@ init_optabs (void) memset_libfunc = init_one_libfunc ("memset"); setbits_libfunc = init_one_libfunc ("__setbits"); - 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"); @@ -627,11 +627,8 @@ decode_options (unsigned int argc, const char **argv) modify it. */ target_flags = targetm.default_target_flags; - /* Unwind tables are always present when a target has ABI-specified unwind - tables, so the default should be ON. */ -#ifdef TARGET_UNWIND_INFO - flag_unwind_tables = TARGET_UNWIND_INFO; -#endif + /* Some tagets have ABI-specified unwind tables. */ + flag_unwind_tables = targetm.unwind_tables_default; #ifdef OPTIMIZATION_OPTIONS /* Allow default optimizations to be specified on a per-machine basis. */ diff --git a/gcc/target-def.h b/gcc/target-def.h index cdaf3d3..9998a19 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -70,6 +70,10 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define TARGET_ASM_INTERNAL_LABEL default_internal_label #endif +#ifndef TARGET_ARM_TTYPE +#define TARGET_ASM_TTYPE hook_bool_rtx_false +#endif + #ifndef TARGET_ASM_ASSEMBLE_VISIBILITY #define TARGET_ASM_ASSEMBLE_VISIBILITY default_assemble_visibility #endif @@ -217,6 +221,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. TARGET_ASM_EMIT_UNWIND_LABEL, \ TARGET_UNWIND_EMIT, \ TARGET_ASM_INTERNAL_LABEL, \ + TARGET_ASM_TTYPE, \ TARGET_ASM_ASSEMBLE_VISIBILITY, \ TARGET_ASM_FUNCTION_PROLOGUE, \ TARGET_ASM_FUNCTION_END_PROLOGUE, \ @@ -401,6 +406,8 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define TARGET_STACK_PROTECT_GUARD default_stack_protect_guard #define TARGET_STACK_PROTECT_FAIL default_external_stack_protect_fail +#define TARGET_ARM_EABI_UNWINDER false + #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_false #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_false #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_false @@ -444,6 +451,9 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN \ } +#ifndef TARGET_UNWIND_TABLES_DEFAULT +#define TARGET_UNWIND_TABLES_DEFAULT false +#endif #ifndef TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME #define TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME 0 @@ -506,7 +516,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. TARGET_CXX_KEY_METHOD_MAY_BE_INLINE, \ TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY, \ TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT, \ - TARGET_CXX_USE_AEABI_ATEXIT \ + TARGET_CXX_USE_AEABI_ATEXIT, \ } /* The whole shebang. */ @@ -572,6 +582,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. TARGET_INVALID_WITHIN_DOLOOP, \ TARGET_CALLS, \ TARGET_CXX, \ + TARGET_UNWIND_TABLES_DEFAULT, \ TARGET_HAVE_NAMED_SECTIONS, \ TARGET_HAVE_CTORS_DTORS, \ TARGET_HAVE_TLS, \ @@ -582,6 +593,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME, \ TARGET_HANDLE_PRAGMA_EXTERN_PREFIX, \ TARGET_RELAXED_ORDERING, \ + TARGET_ARM_EABI_UNWINDER \ } #include "hooks.h" diff --git a/gcc/target.h b/gcc/target.h index 87e644b..364e95a 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -93,6 +93,9 @@ struct gcc_target /* Output an internal label. */ void (* internal_label) (FILE *, const char *, unsigned long); + /* Emit a ttype table reference to a typeinfo object. */ + bool (* ttype) (rtx); + /* Emit an assembler directive to set visibility for the symbol associated with the tree decl. */ void (* visibility) (tree, int); @@ -635,6 +638,9 @@ struct gcc_target bool (*use_aeabi_atexit) (void); } cxx; + /* True if unwinding tables should be generated by default. */ + bool unwind_tables_default; + /* Leave the boolean fields at the end. */ /* True if arbitrary sections are supported. */ @@ -671,6 +677,11 @@ struct gcc_target synchronization is explicitly requested. */ bool relaxed_ordering; + /* Returns true if we should generate exception tables for use with the + ARM EABI. The effects the encoding of function exception specifications. + */ + bool arm_eabi_unwinder; + /* Leave the boolean fields at the end. */ }; diff --git a/gcc/unwind-c.c b/gcc/unwind-c.c index fc76edb..6fb66e0 100644 --- a/gcc/unwind-c.c +++ b/gcc/unwind-c.c @@ -81,6 +81,20 @@ parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p, return p; } +#ifdef __ARM_EABI_UNWINDER__ +/* ARM EABI personality routines must also unwind the stack. */ +#define CONTINUE_UNWINDING \ + do \ + { \ + if (__gnu_unwind_frame (ue_header, context) != _URC_OK) \ + return _URC_FAILURE; \ + return _URC_CONTINUE_UNWIND; \ + } \ + while (0) +#else +#define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND +#endif + #ifdef __USING_SJLJ_EXCEPTIONS__ #define PERSONALITY_FUNCTION __gcc_personality_sj0 #define __builtin_eh_return_data_regno(x) x @@ -88,6 +102,16 @@ parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p, #define PERSONALITY_FUNCTION __gcc_personality_v0 #endif +#ifdef __ARM_EABI_UNWINDER__ +_Unwind_Reason_Code +PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *, + struct _Unwind_Context *); + +_Unwind_Reason_Code +PERSONALITY_FUNCTION (_Unwind_State state, + struct _Unwind_Exception * ue_header, + struct _Unwind_Context * context) +#else _Unwind_Reason_Code PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, struct _Unwind_Context *); @@ -98,24 +122,37 @@ PERSONALITY_FUNCTION (int version, _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED, struct _Unwind_Exception *ue_header, struct _Unwind_Context *context) +#endif { lsda_header_info info; const unsigned char *language_specific_data, *p, *action_record; _Unwind_Ptr landing_pad, ip; +#ifdef __ARM_EABI_UNWINDER__ + if (state != _US_UNWIND_FRAME_STARTING) + CONTINUE_UNWINDING; + + /* The dwarf unwinder assumes the context structure holds things like the + function and LSDA pointers. The ARM implementation caches these in + the exception header (UCB). To avoid rewriting everything we make the + virtual IP register point at the UCB. */ + ip = (_Unwind_Ptr) ue_header; + _Unwind_SetGR (context, 12, ip); +#else if (version != 1) return _URC_FATAL_PHASE1_ERROR; /* Currently we only support cleanups for C. */ if ((actions & _UA_CLEANUP_PHASE) == 0) - return _URC_CONTINUE_UNWIND; + CONTINUE_UNWINDING; +#endif 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; + CONTINUE_UNWINDING; /* Parse the LSDA header. */ p = parse_lsda_header (context, language_specific_data, &info); @@ -171,20 +208,19 @@ PERSONALITY_FUNCTION (int version, goto found_something; } } - #endif /* IP is not in table. No associated cleanups. */ /* ??? This is where C++ calls std::terminate to catch throw from a destructor. */ - return _URC_CONTINUE_UNWIND; + CONTINUE_UNWINDING; found_something: if (landing_pad == 0) { /* IP is present, but has a null landing pad. No handler to be run. */ - return _URC_CONTINUE_UNWIND; + CONTINUE_UNWINDING; } _Unwind_SetGR (context, __builtin_eh_return_data_regno (0), |