This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH, spu, unwind] Remove attribute ((mode (word))) from unwind.h


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
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]