This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH, spu, unwind] Remove attribute ((mode (word))) from unwind.h
- From: "Richard Guenther" <richard dot guenther at gmail dot com>
- To: "Ulrich Weigand" <uweigand at de dot ibm dot com>
- Cc: gcc-patches at gcc dot gnu dot org, trevor_smigiel at playstation dot sony dot com, andrew_pinski at playstation dot sony dot com
- Date: Tue, 17 Jun 2008 14:33:26 -0400
- Subject: Re: [PATCH, spu, unwind] Remove attribute ((mode (word))) from unwind.h
- References: <200806151551.m5FFppPc020872@d12av02.megacenter.de.ibm.com>
On Sun, Jun 15, 2008 at 11:51 AM, Ulrich Weigand <uweigand@de.ibm.com> wrote:
> Hello,
>
> exception handling on the SPU is currently quite broken, due to
> mode mismatches relating to the _Unwind_Word data type.
>
> This data type is defined in the (exported) unwind.h header, and
> forms part of the unwinder ABI as type of members of _Unwind_Exception
> (private_1 and private_2) as well as argument/return type of a number
> of _Unwind_... routines (_Unwind_SetGR, _Unwind_GetGR, _Unwind_GetCFA
> and _Unwind_GetBSP).
>
> It is also used internally to the unwinders (e.g. as members of
> _Unwind_Context and SjLj_Function_Context) in contexts where it
> forms (deliberately or accidentally) part of the ABI.
>
> The type is currently defined via attribute ((mode (__word__))).
> This has already been seen as unfortunate on other platforms
> (e.g. when we tried to implement a mode compatible to the 31-bit
> S/390 ABI that allows internal use of 64-bit registers).
>
> It is particularly bad on the SPU, where word mode is TImode as we have
> 128-bit registers; however, using a 128-bit type as _Unwind_Word is
> completely unnecessary -- it only ever holds target pointers (or in
> some cases, small integers). We don't want to perform 128-bit
> arithmetic throughout the unwinders. (Also, existing out-of-tree
> ports of GCC for SPU are hacked to use a 32-bit _Unwind_Word --
> if at all possible, it would be nice to retain binary compatibility
> with those.)
>
> The SPU back-end currently appears to try to "hack" around this problem
> by building libgcc with -D__word__=SI. The only thing this affects is
> the definition of _Unwind_Word (and _Unwind_Sword). However, this does
> not actually solve the problem because the unwind.h header gets exported
> and used to compile e.g. libstdc++ -- where this define does not apply.
> Also, code in unwind-sjlj.c makes assumptions about the size of the
> _Unwind_Word type that no longer hold.
>
> To solve this problem, I'd propose to allow the target to define the
> mode to be used for _Unwind_Word on the platform. The patch below
> does this by adding a new target macro "targetm.unwind_word_mode ()"
> analogous to some existing macros defining target-specific modes.
>
> This mode is exported to source code via the "unwind_word" mode
> attribute -- this is private and undocumented and intended solely to
> be used in one place: the definition of _Unwind_Word in unwind.h.
>
> In addition, a number of other places that make assumptions about
> the _Unwind_Word type need to be adapted:
>
> - Code in except.c used for SJLJ exception handling constructs a type
> intended to mirror the SjLj_Function_Context type defined in
> unwind-sjlj.c. The latter contains a member of type _Unwind_Word;
> except.c used word_mode to represent that type.
>
> - The __builtin_extend_pointer function returns values of type _Unwind_Word
> (intended solely as input to _Unwind_SetGR which takes _Unwind_Word).
>
>
> There is one already existing target macro targetm.eh_return_filter_mode (),
> which also defines a mode used for exception handling. I understand this
> was introduced to allow using a 64-bit word_mode while remaining compatible
> to the 32-bit ABI on Darwin. It seems that this only ever provided partial
> support for this problem: it doesn't work for SJLJ exceptions (the function
> sjlj_emit_dispatch_table emits a direct move between a word_mode MEM rtx
> and the crtl->eh.filter REG rtx -- this will fail if eh_return_filter_mode
> is ever set to any non-default value); and it does not allow rebuilding
> the base libraries because eh_return_filter_mode is only applied when
> *reading* the EH data filter register, not when setting it (this is always
> done via _Unwind_SetGR).
>
> In the patch below, I'm defaulting targetm.eh_return_filter_mode () to
> return targetm.unwind_word_mode () instead of word_mode, and add a conversion
> to sjlj_emit_dispatch_table in case a non-default eh_return_filter_mode
> is used. However, I suspect that the right thing to do would be to move
> the -to my knowledge- only existing user of eh_return_filter_mode (Darwin)
> to use unwind_word_mode instead ...
>
>
> Tested together with the reg_align spu backend fix on spu-elf,
> fixes the following testsuite FAILs without introducing any
> regressions:
>
> FAIL: gcc.dg/cleanup-12.c execution test
> FAIL: gcc.dg/cleanup-5.c execution test
> FAIL: g++.dg/compat/eh/ctor1 cp_compat_x_tst.o-cp_compat_y_tst.o execute
> FAIL: g++.dg/compat/eh/ctor2 cp_compat_x_tst.o-cp_compat_y_tst.o execute
> FAIL: g++.dg/compat/eh/dtor1 cp_compat_x_tst.o-cp_compat_y_tst.o execute
> FAIL: g++.dg/compat/eh/filter1 cp_compat_x_tst.o-cp_compat_y_tst.o execute
> FAIL: g++.dg/compat/eh/new1 cp_compat_x_tst.o-cp_compat_y_tst.o execute
> FAIL: g++.dg/compat/eh/nrv1 cp_compat_x_tst.o-cp_compat_y_tst.o execute
> FAIL: g++.dg/compat/eh/template1 cp_compat_x_tst.o-cp_compat_y_tst.o execute
> FAIL: g++.dg/compat/eh/unexpected1 cp_compat_x_tst.o-cp_compat_y_tst.o execute
> FAIL: g++.dg/compat/init/array5 cp_compat_x_tst.o-cp_compat_y_tst.o execute
> FAIL: g++.dg/cpp0x/variadic73.C execution test
> FAIL: g++.dg/eh/alias1.C execution test
> FAIL: g++.dg/eh/cond1.C execution test
> FAIL: g++.dg/eh/crossjump1.C execution test
> FAIL: g++.dg/eh/ctor1.C execution test
> FAIL: g++.dg/eh/ctor2.C execution test
> FAIL: g++.dg/eh/delayslot1.C execution test
> FAIL: g++.dg/eh/dtor1.C execution test
> FAIL: g++.dg/eh/elide1.C execution test
> FAIL: g++.dg/eh/forced1.C execution test
> FAIL: g++.dg/eh/forced2.C execution test
> FAIL: g++.dg/eh/forced3.C execution test
> FAIL: g++.dg/eh/forced4.C execution test
> FAIL: g++.dg/eh/fp-regs.C execution test
> FAIL: g++.dg/eh/gcsec1.C execution test
> FAIL: g++.dg/eh/ia64-2.C execution test
> FAIL: g++.dg/eh/loop1.C execution test
> FAIL: g++.dg/eh/loop2.C execution test
> FAIL: g++.dg/eh/new1.C execution test
> FAIL: g++.dg/eh/omit-frame-pointer2.C execution test
> FAIL: g++.dg/eh/pr29166.C execution test
> FAIL: g++.dg/eh/registers1.C execution test
> FAIL: g++.dg/eh/simd-1.C execution test
> FAIL: g++.dg/eh/simd-2.C execution test
> FAIL: g++.dg/eh/simd-3.C execution test
> FAIL: g++.dg/eh/spbp.C execution test
> FAIL: g++.dg/eh/spec3.C execution test
> FAIL: g++.dg/eh/spec7.C execution test
> FAIL: g++.dg/eh/spec9.C execution test
> FAIL: g++.dg/eh/synth2.C execution test
> FAIL: g++.dg/eh/template1.C execution test
> FAIL: g++.dg/eh/uncaught1.C execution test
> FAIL: g++.dg/eh/unexpected1.C execution test
> FAIL: g++.dg/ext/cleanup-5.C execution test
> FAIL: g++.dg/init/array5.C execution test
> FAIL: g++.dg/init/ctor1.C execution test
> FAIL: g++.dg/init/placement2.C execution test
> FAIL: g++.dg/init/ref9.C execution test
> FAIL: g++.dg/opt/cleanup1.C execution test
> FAIL: g++.dg/opt/eh2.C execution test
> FAIL: g++.dg/opt/eh3.C execution test
> FAIL: g++.dg/tree-ssa/pr19786.C execution test
> FAIL: g++.old-deja/g++.abi/cxa_vec.C execution test
> FAIL: g++.old-deja/g++.brendan/eh1.C execution test
> FAIL: g++.old-deja/g++.eh/badalloc1.C execution test
> FAIL: g++.old-deja/g++.eh/catch11.C execution test
> FAIL: g++.old-deja/g++.eh/catch12.C execution test
> FAIL: g++.old-deja/g++.eh/catch3.C execution test
> FAIL: g++.old-deja/g++.eh/catch3p.C execution test
> FAIL: g++.old-deja/g++.eh/catch4.C execution test
> FAIL: g++.old-deja/g++.eh/catch4p.C execution test
> FAIL: g++.old-deja/g++.eh/catch5p.C execution test
> FAIL: g++.old-deja/g++.eh/catch6.C execution test
> FAIL: g++.old-deja/g++.eh/catch6p.C execution test
> FAIL: g++.old-deja/g++.eh/catch7.C execution test
> FAIL: g++.old-deja/g++.eh/catch8.C execution test
> FAIL: g++.old-deja/g++.eh/catch8p.C execution test
> FAIL: g++.old-deja/g++.eh/catch9.C execution test
> FAIL: g++.old-deja/g++.eh/catch9p.C execution test
> FAIL: g++.old-deja/g++.eh/catchptr1.C execution test
> FAIL: g++.old-deja/g++.eh/cleanup1.C execution test
> FAIL: g++.old-deja/g++.eh/cleanup2.C execution test
> FAIL: g++.old-deja/g++.eh/flow1.C execution test
> FAIL: g++.old-deja/g++.eh/fntry1.C execution test
> FAIL: g++.old-deja/g++.eh/ia64-1.C execution test
> FAIL: g++.old-deja/g++.eh/new1.C execution test
> FAIL: g++.old-deja/g++.eh/new2.C execution test
> FAIL: g++.old-deja/g++.eh/pdel1.C execution test
> FAIL: g++.old-deja/g++.eh/pdel2.C execution test
> FAIL: g++.old-deja/g++.eh/ptr1.C execution test
> FAIL: g++.old-deja/g++.eh/ptrmem1.C execution test
> FAIL: g++.old-deja/g++.eh/rethrow1.C execution test
> FAIL: g++.old-deja/g++.eh/rethrow2.C execution test
> FAIL: g++.old-deja/g++.eh/rethrow3.C execution test
> FAIL: g++.old-deja/g++.eh/rethrow4.C execution test
> FAIL: g++.old-deja/g++.eh/rethrow5.C execution test
> FAIL: g++.old-deja/g++.eh/rethrow6.C execution test
> FAIL: g++.old-deja/g++.eh/spec1.C execution test
> FAIL: g++.old-deja/g++.eh/spec2.C execution test
> FAIL: g++.old-deja/g++.eh/spec3.C execution test
> FAIL: g++.old-deja/g++.eh/tmpl1.C execution test
> FAIL: g++.old-deja/g++.eh/unwind1.C execution test
> FAIL: g++.old-deja/g++.eh/vbase1.C execution test
> FAIL: g++.old-deja/g++.eh/vbase2.C execution test
> FAIL: g++.old-deja/g++.eh/vbase4.C execution test
> FAIL: g++.old-deja/g++.martin/new1.C execution test
> FAIL: g++.old-deja/g++.mike/dyncast1.C execution test
> FAIL: g++.old-deja/g++.mike/dyncast2.C execution test
> FAIL: g++.old-deja/g++.mike/eh10.C execution test
> FAIL: g++.old-deja/g++.mike/eh12.C execution test
> FAIL: g++.old-deja/g++.mike/eh14.C execution test
> FAIL: g++.old-deja/g++.mike/eh16.C execution test
> FAIL: g++.old-deja/g++.mike/eh17.C execution test
> FAIL: g++.old-deja/g++.mike/eh18.C execution test
> FAIL: g++.old-deja/g++.mike/eh21.C execution test
> FAIL: g++.old-deja/g++.mike/eh24.C execution test
> FAIL: g++.old-deja/g++.mike/eh25.C execution test
> FAIL: g++.old-deja/g++.mike/eh26.C execution test
> FAIL: g++.old-deja/g++.mike/eh27.C execution test
> FAIL: g++.old-deja/g++.mike/eh28.C execution test
> FAIL: g++.old-deja/g++.mike/eh29.C execution test
> FAIL: g++.old-deja/g++.mike/eh3.C execution test
> FAIL: g++.old-deja/g++.mike/eh31.C execution test
> FAIL: g++.old-deja/g++.mike/eh35.C execution test
> FAIL: g++.old-deja/g++.mike/eh36.C execution test
> FAIL: g++.old-deja/g++.mike/eh37.C execution test
> FAIL: g++.old-deja/g++.mike/eh38.C execution test
> FAIL: g++.old-deja/g++.mike/eh39.C execution test
> FAIL: g++.old-deja/g++.mike/eh40.C execution test
> FAIL: g++.old-deja/g++.mike/eh41.C execution test
> FAIL: g++.old-deja/g++.mike/eh42.C execution test
> FAIL: g++.old-deja/g++.mike/eh44.C execution test
> FAIL: g++.old-deja/g++.mike/eh48.C execution test
> FAIL: g++.old-deja/g++.mike/eh49.C execution test
> FAIL: g++.old-deja/g++.mike/eh5.C execution test
> FAIL: g++.old-deja/g++.mike/eh50.C execution test
> FAIL: g++.old-deja/g++.mike/eh51.C execution test
> FAIL: g++.old-deja/g++.mike/eh6.C execution test
> FAIL: g++.old-deja/g++.mike/eh8.C execution test
> FAIL: g++.old-deja/g++.mike/p7912.C execution test
> FAIL: g++.old-deja/g++.mike/p9706.C execution test
> FAIL: g++.old-deja/g++.oliva/delete3.C execution test
> FAIL: g++.old-deja/g++.oliva/new1.C execution test
> FAIL: g++.old-deja/g++.other/array1.C execution test
> FAIL: g++.old-deja/g++.other/eh3.C execution test
> FAIL: g++.old-deja/g++.other/init7.C execution test
> FAIL: g++.old-deja/g++.other/new7.C execution test
> FAIL: g++.old-deja/g++.other/singleton.C execution test
> FAIL: g++.old-deja/g++.other/vbase2.C execution test
> FAIL: g++.old-deja/g++.robertl/eb50.C execution test
> FAIL: g++.old-deja/g++.robertl/eb88.C execution test
> FAIL: g++.old-deja/g++.robertl/eh990323-1.C execution test
> FAIL: g++.old-deja/g++.robertl/eh990323-2.C execution test
> FAIL: g++.old-deja/g++.robertl/eh990323-3.C execution test
> FAIL: g++.old-deja/g++.robertl/eh990323-4.C execution test
> FAIL: g++.old-deja/g++.robertl/eh990323-5.C execution test
> FAIL: g++.old-deja/g++.robertl/ice990323-2.C execution test
>
> OK for mainline and 4.3 branch?
This is ok for the trunk and for the branch after a while.
Thanks,
Richard.
> Bye,
> Ulrich
>
>
> ChangeLog:
>
> * targhooks.h (struct gcc_target): New member unwind_word_mode.
> (default_unwind_word_mode): Add prototype.
> * targhooks.c (default_unwind_word_mode): New function.
> (default_eh_return_filter_mode): Return targetm.unwind_word_mode ()
> instead of word_mode.
> * target-def.h (TARGET_UNWIND_WORD_MODE): New macro.
> (TARGET_INITIALIZER): Use it.
>
> * c-common.c (handle_mode_attribute): Support "unwind_word"
> mode attribute.
> * unwind-generic.h (_Unwind_Word, _Unwind_Sword): Use it.
>
> * except.c (init_eh): Use targetm.unwind_word_mode () instead of
> word_mode to access SjLj_Function_Context member "data".
> (sjlj_emit_dispatch_table): Likewise. Also, perform type
> conversion from targetm.eh_return_filter_mode () to
> targetm.unwind_word_mode () if they differ.
>
> * builtin-types.def (BT_UNWINDWORD): New primitive type.
> (BT_FN_UNWINDWORD_PTR): New function type.
> (BT_FN_WORD_PTR): Remove.
> * builtins.def (BUILT_IN_EXTEND_POINTER): Use BT_FN_UNWINDWORD_PTR.
> * except.c (expand_builtin_extend_pointer): Convert pointer to
> targetm.unwind_word_mode () instead of word_mode.
>
> * config/spu/spu-protos.h (spu_eh_return_filter_mode): Remove.
> * config/spu/spu.c (spu_eh_return_filter_mode): Remove.
> (spu_unwind_word_mode): New function.
> (TARGET_EH_RETURN_FILTER_MODE): Do not define.
> (TARGET_UNWIND_WORD_MODE): Define.
> * config/spu/t-spu-elf (TARGET_LIBGCC2_CFLAGS): Remove -D__word__=SI.
>
>
> Index: gcc/targhooks.c
> ===================================================================
> *** gcc/targhooks.c (revision 136680)
> --- gcc/targhooks.c (working copy)
> *************** default_pretend_outgoing_varargs_named (
> *** 152,158 ****
> enum machine_mode
> default_eh_return_filter_mode (void)
> {
> ! return word_mode;
> }
>
> enum machine_mode
> --- 152,158 ----
> enum machine_mode
> default_eh_return_filter_mode (void)
> {
> ! return targetm.unwind_word_mode ();
> }
>
> enum machine_mode
> *************** default_libgcc_shift_count_mode (void)
> *** 167,172 ****
> --- 167,178 ----
> return word_mode;
> }
>
> + enum machine_mode
> + default_unwind_word_mode (void)
> + {
> + return word_mode;
> + }
> +
> /* The default implementation of TARGET_SHIFT_TRUNCATION_MASK. */
>
> unsigned HOST_WIDE_INT
> Index: gcc/targhooks.h
> ===================================================================
> *** gcc/targhooks.h (revision 136680)
> --- gcc/targhooks.h (working copy)
> *************** extern bool default_pretend_outgoing_var
> *** 34,39 ****
> --- 34,40 ----
> extern enum machine_mode default_eh_return_filter_mode (void);
> extern enum machine_mode default_libgcc_cmp_return_mode (void);
> extern enum machine_mode default_libgcc_shift_count_mode (void);
> + extern enum machine_mode default_unwind_word_mode (void);
> extern unsigned HOST_WIDE_INT default_shift_truncation_mask
> (enum machine_mode);
> extern unsigned int default_min_divisions_for_recip_mul (enum machine_mode);
> Index: gcc/target.h
> ===================================================================
> *** gcc/target.h (revision 136680)
> --- gcc/target.h (working copy)
> *************** struct gcc_target
> *** 463,468 ****
> --- 463,471 ----
> /* Return machine mode for libgcc expanded shift instructions. */
> enum machine_mode (* libgcc_shift_count_mode) (void);
>
> + /* Return machine mode to be used for _Unwind_Word type. */
> + enum machine_mode (* unwind_word_mode) (void);
> +
> /* Given two decls, merge their attributes and return the result. */
> tree (* merge_decl_attributes) (tree, tree);
>
> Index: gcc/builtin-types.def
> ===================================================================
> *** gcc/builtin-types.def (revision 136680)
> --- gcc/builtin-types.def (working copy)
> *************** DEF_PRIMITIVE_TYPE (BT_UINTMAX, uintmax_
> *** 77,82 ****
> --- 77,84 ----
> DEF_PRIMITIVE_TYPE (BT_UINT32, uint32_type_node)
> DEF_PRIMITIVE_TYPE (BT_UINT64, uint64_type_node)
> DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
> + DEF_PRIMITIVE_TYPE (BT_UNWINDWORD, (*lang_hooks.types.type_for_mode)
> + (targetm.unwind_word_mode (), 1))
> DEF_PRIMITIVE_TYPE (BT_FLOAT, float_type_node)
> DEF_PRIMITIVE_TYPE (BT_DOUBLE, double_type_node)
> DEF_PRIMITIVE_TYPE (BT_LONGDOUBLE, long_double_type_node)
> *************** DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_CONS
> *** 203,209 ****
> DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_CONST_STRING,
> BT_DFLOAT128, BT_CONST_STRING)
> DEF_FUNCTION_TYPE_1 (BT_FN_STRING_CONST_STRING, BT_STRING, BT_CONST_STRING)
> ! DEF_FUNCTION_TYPE_1 (BT_FN_WORD_PTR, BT_WORD, BT_PTR)
> DEF_FUNCTION_TYPE_1 (BT_FN_INT_WINT, BT_INT, BT_WINT)
> DEF_FUNCTION_TYPE_1 (BT_FN_WINT_WINT, BT_WINT, BT_WINT)
> DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_DFLOAT32, BT_DFLOAT32, BT_DFLOAT32)
> --- 205,211 ----
> DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_CONST_STRING,
> BT_DFLOAT128, BT_CONST_STRING)
> DEF_FUNCTION_TYPE_1 (BT_FN_STRING_CONST_STRING, BT_STRING, BT_CONST_STRING)
> ! DEF_FUNCTION_TYPE_1 (BT_FN_UNWINDWORD_PTR, BT_UNWINDWORD, BT_PTR)
> DEF_FUNCTION_TYPE_1 (BT_FN_INT_WINT, BT_INT, BT_WINT)
> DEF_FUNCTION_TYPE_1 (BT_FN_WINT_WINT, BT_WINT, BT_WINT)
> DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_DFLOAT32, BT_DFLOAT32, BT_DFLOAT32)
> Index: gcc/builtins.def
> ===================================================================
> *** gcc/builtins.def (revision 136680)
> --- gcc/builtins.def (working copy)
> *************** DEF_EXT_LIB_BUILTIN (BUILT_IN_EXE
> *** 635,641 ****
> DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVE, "execve", BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST)
> DEF_LIB_BUILTIN (BUILT_IN_EXIT, "exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
> DEF_GCC_BUILTIN (BUILT_IN_EXPECT, "expect", BT_FN_LONG_LONG_LONG, ATTR_CONST_NOTHROW_LIST)
> ! DEF_GCC_BUILTIN (BUILT_IN_EXTEND_POINTER, "extend_pointer", BT_FN_WORD_PTR, ATTR_CONST_NOTHROW_LIST)
> DEF_GCC_BUILTIN (BUILT_IN_EXTRACT_RETURN_ADDR, "extract_return_addr", BT_FN_PTR_PTR, ATTR_NULL)
> DEF_EXT_LIB_BUILTIN (BUILT_IN_FFS, "ffs", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
> DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSIMAX, "ffsimax", BT_FN_INT_INTMAX, ATTR_CONST_NOTHROW_LIST)
> --- 635,641 ----
> DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVE, "execve", BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST)
> DEF_LIB_BUILTIN (BUILT_IN_EXIT, "exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
> DEF_GCC_BUILTIN (BUILT_IN_EXPECT, "expect", BT_FN_LONG_LONG_LONG, ATTR_CONST_NOTHROW_LIST)
> ! DEF_GCC_BUILTIN (BUILT_IN_EXTEND_POINTER, "extend_pointer", BT_FN_UNWINDWORD_PTR, ATTR_CONST_NOTHROW_LIST)
> DEF_GCC_BUILTIN (BUILT_IN_EXTRACT_RETURN_ADDR, "extract_return_addr", BT_FN_PTR_PTR, ATTR_NULL)
> DEF_EXT_LIB_BUILTIN (BUILT_IN_FFS, "ffs", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
> DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSIMAX, "ffsimax", BT_FN_INT_INTMAX, ATTR_CONST_NOTHROW_LIST)
> Index: gcc/except.c
> ===================================================================
> *** gcc/except.c (revision 136680)
> --- gcc/except.c (working copy)
> *************** init_eh (void)
> *** 338,344 ****
> DECL_FIELD_CONTEXT (f_cs) = sjlj_fc_type_node;
>
> tmp = build_index_type (build_int_cst (NULL_TREE, 4 - 1));
> ! tmp = build_array_type (lang_hooks.types.type_for_mode (word_mode, 1),
> tmp);
> f_data = build_decl (FIELD_DECL, get_identifier ("__data"), tmp);
> DECL_FIELD_CONTEXT (f_data) = sjlj_fc_type_node;
> --- 338,345 ----
> DECL_FIELD_CONTEXT (f_cs) = sjlj_fc_type_node;
>
> tmp = build_index_type (build_int_cst (NULL_TREE, 4 - 1));
> ! tmp = build_array_type (lang_hooks.types.type_for_mode
> ! (targetm.unwind_word_mode (), 1),
> tmp);
> f_data = build_decl (FIELD_DECL, get_identifier ("__data"), tmp);
> DECL_FIELD_CONTEXT (f_data) = sjlj_fc_type_node;
> *************** sjlj_emit_function_exit (void)
> *** 1932,1937 ****
> --- 1933,1940 ----
> static void
> sjlj_emit_dispatch_table (rtx dispatch_label, struct sjlj_lp_info *lp_info)
> {
> + enum machine_mode unwind_word_mode = targetm.unwind_word_mode ();
> + enum machine_mode filter_mode = targetm.eh_return_filter_mode ();
> int i, first_reachable;
> rtx mem, dispatch, seq, fc;
> rtx before;
> *************** sjlj_emit_dispatch_table (rtx dispatch_l
> *** 1954,1961 ****
> sjlj_fc_call_site_ofs);
> dispatch = copy_to_reg (mem);
>
> ! mem = adjust_address (fc, word_mode, sjlj_fc_data_ofs);
> ! if (word_mode != ptr_mode)
> {
> #ifdef POINTERS_EXTEND_UNSIGNED
> mem = convert_memory_address (ptr_mode, mem);
> --- 1957,1964 ----
> sjlj_fc_call_site_ofs);
> dispatch = copy_to_reg (mem);
>
> ! mem = adjust_address (fc, unwind_word_mode, sjlj_fc_data_ofs);
> ! if (unwind_word_mode != ptr_mode)
> {
> #ifdef POINTERS_EXTEND_UNSIGNED
> mem = convert_memory_address (ptr_mode, mem);
> *************** sjlj_emit_dispatch_table (rtx dispatch_l
> *** 1965,1971 ****
> }
> emit_move_insn (crtl->eh.exc_ptr, mem);
>
> ! mem = adjust_address (fc, word_mode, sjlj_fc_data_ofs + UNITS_PER_WORD);
> emit_move_insn (crtl->eh.filter, mem);
>
> /* Jump to one of the directly reachable regions. */
> --- 1968,1977 ----
> }
> emit_move_insn (crtl->eh.exc_ptr, mem);
>
> ! mem = adjust_address (fc, unwind_word_mode,
> ! sjlj_fc_data_ofs + GET_MODE_SIZE (unwind_word_mode));
> ! if (unwind_word_mode != filter_mode)
> ! mem = convert_to_mode (filter_mode, mem, 0);
> emit_move_insn (crtl->eh.filter, mem);
>
> /* Jump to one of the directly reachable regions. */
> *************** expand_builtin_extend_pointer (tree addr
> *** 3002,3008 ****
> extend = 1;
> #endif
>
> ! return convert_modes (word_mode, ptr_mode, addr, extend);
> }
>
> /* In the following functions, we represent entries in the action table
> --- 3008,3014 ----
> extend = 1;
> #endif
>
> ! return convert_modes (targetm.unwind_word_mode (), ptr_mode, addr, extend);
> }
>
> /* In the following functions, we represent entries in the action table
> Index: gcc/target-def.h
> ===================================================================
> *** gcc/target-def.h (revision 136680)
> --- gcc/target-def.h (working copy)
> ***************
> *** 388,393 ****
> --- 388,396 ----
> #define TARGET_LIBGCC_CMP_RETURN_MODE default_libgcc_cmp_return_mode
> #define TARGET_LIBGCC_SHIFT_COUNT_MODE default_libgcc_shift_count_mode
>
> + /* In unwind-generic.h. */
> + #define TARGET_UNWIND_WORD_MODE default_unwind_word_mode
> +
> /* In tree.c. */
> #define TARGET_MERGE_DECL_ATTRIBUTES merge_decl_attributes
> #define TARGET_MERGE_TYPE_ATTRIBUTES merge_type_attributes
> ***************
> *** 761,766 ****
> --- 764,770 ----
> TARGET_EH_RETURN_FILTER_MODE, \
> TARGET_LIBGCC_CMP_RETURN_MODE, \
> TARGET_LIBGCC_SHIFT_COUNT_MODE, \
> + TARGET_UNWIND_WORD_MODE, \
> TARGET_MERGE_DECL_ATTRIBUTES, \
> TARGET_MERGE_TYPE_ATTRIBUTES, \
> TARGET_ATTRIBUTE_TABLE, \
> Index: gcc/c-common.c
> ===================================================================
> *** gcc/c-common.c (revision 136680)
> --- gcc/c-common.c (working copy)
> *************** handle_mode_attribute (tree *node, tree
> *** 5292,5297 ****
> --- 5292,5299 ----
> mode = targetm.libgcc_cmp_return_mode ();
> else if (!strcmp (p, "libgcc_shift_count"))
> mode = targetm.libgcc_shift_count_mode ();
> + else if (!strcmp (p, "unwind_word"))
> + mode = targetm.unwind_word_mode ();
> else
> for (j = 0; j < NUM_MACHINE_MODES; j++)
> if (!strcmp (p, GET_MODE_NAME (j)))
> Index: gcc/unwind-generic.h
> ===================================================================
> *** gcc/unwind-generic.h (revision 136680)
> --- gcc/unwind-generic.h (working copy)
> *************** extern "C" {
> *** 43,50 ****
>
> /* @@@ 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__)));
> #if defined(__ia64__) && defined(__hpux__)
> typedef unsigned _Unwind_Ptr __attribute__((__mode__(__word__)));
> #else
> --- 43,50 ----
>
> /* @@@ The IA-64 ABI uses uint64 throughout. Most places this is
> inefficient for 32-bit and smaller machines. */
> ! typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__)));
> ! typedef signed _Unwind_Sword __attribute__((__mode__(__unwind_word__)));
> #if defined(__ia64__) && defined(__hpux__)
> typedef unsigned _Unwind_Ptr __attribute__((__mode__(__word__)));
> #else
> Index: gcc/config/spu/spu-protos.h
> ===================================================================
> *** gcc/config/spu/spu-protos.h (revision 136680)
> --- gcc/config/spu/spu-protos.h (working copy)
> ***************
> *** 19,25 ****
>
> #include "rtl.h"
>
> - extern enum machine_mode spu_eh_return_filter_mode (void);
> extern void spu_cpu_cpp_builtins (struct cpp_reader * pfile);
> extern void builtin_define_std (const char *);
> extern void spu_optimization_options (int level, int size);
> --- 19,24 ----
> *************** extern rtx gen_cpat_const (rtx * ops);
> *** 76,82 ****
> extern void constant_to_array (enum machine_mode mode, rtx x,
> unsigned char *arr);
> extern rtx array_to_constant (enum machine_mode mode, unsigned char *arr);
> - extern enum machine_mode spu_eh_return_filter_mode (void);
> extern void spu_allocate_stack (rtx op0, rtx op1);
> extern void spu_restore_stack_nonlocal (rtx op0, rtx op1);
> extern void spu_restore_stack_block (rtx op0, rtx op1);
> --- 75,80 ----
> Index: gcc/config/spu/spu.c
> ===================================================================
> *** gcc/config/spu/spu.c (revision 136680)
> --- gcc/config/spu/spu.c (working copy)
> *************** static int cpat_info(unsigned char *arr,
> *** 177,182 ****
> --- 177,184 ----
> static enum immediate_class classify_immediate (rtx op,
> enum machine_mode mode);
>
> + static enum machine_mode spu_unwind_word_mode (void);
> +
> static enum machine_mode
> spu_libgcc_cmp_return_mode (void);
>
> *************** tree spu_builtin_types[SPU_BTI_MAX];
> *** 194,201 ****
> #undef TARGET_EXPAND_BUILTIN
> #define TARGET_EXPAND_BUILTIN spu_expand_builtin
>
> ! #undef TARGET_EH_RETURN_FILTER_MODE
> ! #define TARGET_EH_RETURN_FILTER_MODE spu_eh_return_filter_mode
>
> /* The .8byte directive doesn't seem to work well for a 32 bit
> architecture. */
> --- 196,203 ----
> #undef TARGET_EXPAND_BUILTIN
> #define TARGET_EXPAND_BUILTIN spu_expand_builtin
>
> ! #undef TARGET_UNWIND_WORD_MODE
> ! #define TARGET_UNWIND_WORD_MODE spu_unwind_word_mode
>
> /* The .8byte directive doesn't seem to work well for a 32 bit
> architecture. */
> *************** spu_rtx_costs (rtx x, int code, int oute
> *** 4316,4327 ****
> return true;
> }
>
> ! enum machine_mode
> ! spu_eh_return_filter_mode (void)
> {
> ! /* We would like this to be SImode, but sjlj exceptions seems to work
> ! only with word_mode. */
> ! return TImode;
> }
>
> /* Decide whether we can make a sibling call to a function. DECL is the
> --- 4318,4327 ----
> return true;
> }
>
> ! static enum machine_mode
> ! spu_unwind_word_mode (void)
> {
> ! return SImode;
> }
>
> /* Decide whether we can make a sibling call to a function. DECL is the
> Index: gcc/config/spu/t-spu-elf
> ===================================================================
> *** gcc/config/spu/t-spu-elf (revision 136680)
> --- gcc/config/spu/t-spu-elf (working copy)
> ***************
> *** 19,27 ****
> LIBGCC1 =
> CROSS_LIBGCC1 =
>
> ! # On SPU __word__ is TImode which is too inefficient and incomplete for
> ! # implementing libgcc routines.
> ! TARGET_LIBGCC2_CFLAGS = -fPIC -D__word__=SI -mwarn-reloc -D__IN_LIBGCC2
>
> LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/spu/float_unssidf.c \
> $(srcdir)/config/spu/float_unsdidf.c \
> --- 19,25 ----
> LIBGCC1 =
> CROSS_LIBGCC1 =
>
> ! TARGET_LIBGCC2_CFLAGS = -fPIC -mwarn-reloc -D__IN_LIBGCC2
>
> LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/spu/float_unssidf.c \
> $(srcdir)/config/spu/float_unsdidf.c \
> --
> Dr. Ulrich Weigand
> GNU Toolchain for Linux on System z and Cell BE
> Ulrich.Weigand@de.ibm.com
>