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]

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


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


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