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

trevor_smigiel@playstation.sony.com trevor_smigiel@playstation.sony.com
Mon Jun 16 20:31:00 GMT 2008


OK for the SPU part.

Trevor

* Ulrich Weigand <uweigand@de.ibm.com> [2008-06-15 08:55]:
> 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?
> 
> 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



More information about the Gcc-patches mailing list