Fix string merging problems on mips*-linux-gnu

Richard Sandiford rsandifo@redhat.com
Sat Jan 10 20:32:00 GMT 2004


This patch fixes -O1 failures for execute/930429-1.c and
execute/ptr-arith-1.c on mips*-linux-gnu.

Suppose we have a string such as:

.LC0: .asciz "x"

and .LC0 is in a mergeable string section.  If we need a "one past
the end" pointer to this string, we can generate an insn such as:

        la      reg,.LC0+2

or its explicit-reloc equivalent.  But the linker will then think
that we're refering to the string after "x", not "x" itself.  There's
no guarantee that the two strings will still be together in the merged
section.

The patch makes sure that all references of the form "string_constant +
offset" refer to a character within the string.  Bootstrapped &
regression tested on mips64{,el}-linux-gnu, fixes the two test cases.
Also tested on mips64vrel-elf to verify the mips16 change.  Does it
look OK?

Richard


	* config/mips/mips.c (mips_symbolic_constant_p): Don't allow
	out-of-bounds accesses to string constants.  Simplify mips16
	case accordingly.

Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.359
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.359 mips.c
*** config/mips/mips.c	5 Jan 2004 09:59:41 -0000	1.359
--- config/mips/mips.c	10 Jan 2004 19:52:22 -0000
*************** mips_symbolic_constant_p (rtx x, enum mi
*** 902,907 ****
--- 902,917 ----
    if (offset == 0)
      return true;
  
+   /* If X refers to a string constant, and that constant is put into a
+      mergeable section, the linker will need to know which string is
+      being accessed.  It has no way of distinguishing an out-of-bounds
+      access to X from an in-bounds access to a later or earlier string.  */
+   if (GET_CODE (x) == SYMBOL_REF
+       && SYMBOL_REF_DECL (x) != 0
+       && TREE_CODE (SYMBOL_REF_DECL (x)) == STRING_CST
+       && !(offset > 0 && offset < TREE_STRING_LENGTH (SYMBOL_REF_DECL (x))))
+     return false;
+ 
    /* Check whether a nonzero offset is valid for the underlying
       relocations.  */
    switch (*symbol_type)
*************** mips_symbolic_constant_p (rtx x, enum mi
*** 917,927 ****
        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:
--- 927,935 ----
        return (offset > 0 && offset < mips_section_threshold);
  
      case SYMBOL_CONSTANT_POOL:
!       /* We don't generate out-of-bounds accesses to normal constant
! 	 pool entries.  String constants were handled above.  */
!       return true;
  
      case SYMBOL_GOT_LOCAL:
      case SYMBOL_GOTOFF_PAGE:



More information about the Gcc-patches mailing list