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]

Fix 960321-1.c for MIPS EABI64


As discussed on the gcc@ list, here's a fix for the 960321-1.c failure.
The patch adds a new function, mips_offset_within_object_p, for checking
whether a particular sym+offset points to the same object as sym.
We can then use this for ABIs where Pmode == DImode but the object
format only supports 32-bit symbols.

The new function is a generalisation of the existing constant pool and
small data range checks, so we can reuse it there too.  This cuts down
the number of special cases and improves references to largish objects
that have been put into a small data section using __attribute__((section)).

Tested on mips64{,el}-linux-gnu and mips64vrel-elf (to get mips16
coverage).  Eric, is this OK with you?

Richard


	* config/mips/mips.c (mips_offset_within_object_p): New function.
	(mips_symbolic_constant_p): Use it in the SYMBOL_SMALL_DATA and
	SYMBOL_CONSTANT_POOL cases.  Also use it for SYMBOL_GENERAL if the
	ABI has 64-bit pointers and the object file only allows 32-bit symbols.

Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.367
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.367 mips.c
*** config/mips/mips.c	25 Jan 2004 10:16:20 -0000	1.367
--- config/mips/mips.c	25 Jan 2004 11:37:32 -0000
*************** struct mips_integer_op;
*** 191,196 ****
--- 191,197 ----
  
  static enum mips_symbol_type mips_classify_symbol (rtx);
  static void mips_split_const (rtx, rtx *, HOST_WIDE_INT *);
+ static bool mips_offset_within_object_p (rtx, HOST_WIDE_INT);
  static bool mips_symbolic_constant_p (rtx, enum mips_symbol_type *);
  static bool mips_valid_base_register_p (rtx, enum machine_mode, int);
  static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
*************** mips_split_const (rtx x, rtx *base, HOST
*** 893,898 ****
--- 894,922 ----
  }
  
  
+ /* Return true if SYMBOL is a SYMBOL_REF and OFFSET + SYMBOL points
+    to the same object as SYMBOL.  */
+ 
+ static bool
+ mips_offset_within_object_p (rtx symbol, HOST_WIDE_INT offset)
+ {
+   if (GET_CODE (symbol) != SYMBOL_REF)
+     return false;
+ 
+   if (CONSTANT_POOL_ADDRESS_P (symbol)
+       && offset >= 0
+       && offset < (int) GET_MODE_SIZE (get_pool_mode (symbol)))
+     return true;
+ 
+   if (SYMBOL_REF_DECL (symbol) != 0
+       && offset >= 0
+       && offset < int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (symbol))))
+     return true;
+ 
+   return false;
+ }
+ 
+ 
  /* Return true if X is a symbolic constant that can be calculated in
     the same way as a bare symbol.  If it is, store the type of the
     symbol in *SYMBOL_TYPE.  */
*************** mips_symbolic_constant_p (rtx x, enum mi
*** 918,938 ****
    switch (*symbol_type)
      {
      case SYMBOL_GENERAL:
!       /* %hi() and %lo() can handle anything.  */
        return true;
  
      case SYMBOL_SMALL_DATA:
-       /* Make sure that the offset refers to something within the
- 	 -G limit.  If the offset is allowed to grow too much,
- 	 it could overflow the range of %gp_rel().  */
-       return (offset > 0 && offset < mips_section_threshold);
- 
      case SYMBOL_CONSTANT_POOL:
!       /* Similarly check the range of offsets for mips16 constant
! 	 pool entries.  */
!       return (CONSTANT_POOL_ADDRESS_P (x)
! 	      && offset > 0
! 	      && offset < (int) GET_MODE_SIZE (get_pool_mode (x)));
  
      case SYMBOL_GOT_LOCAL:
      case SYMBOL_GOTOFF_PAGE:
--- 942,963 ----
    switch (*symbol_type)
      {
      case SYMBOL_GENERAL:
!       /* If the target has 64-bit pointers and the object file only
! 	 supports 32-bit symbols, the values of those symbols will be
! 	 sign-extended.  In this case we can't allow an arbitrary offset
! 	 in case the 32-bit value X + OFFSET has a different sign from X.  */
!       if (Pmode == DImode && !ABI_HAS_64BIT_SYMBOLS)
! 	return mips_offset_within_object_p (x, offset);
! 
!       /* In other cases the relocations can handle any offset.  */
        return true;
  
      case SYMBOL_SMALL_DATA:
      case SYMBOL_CONSTANT_POOL:
!       /* Make sure that the offset refers to something within the
! 	 underlying object.  This should guarantee that the final
! 	 PC- or GP-relative offset is within the 16-bit limit.  */
!       return mips_offset_within_object_p (x, offset);
  
      case SYMBOL_GOT_LOCAL:
      case SYMBOL_GOTOFF_PAGE:


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