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]

[committed] Fix PR16407: Unaligned access to local vars


This patch fixes PR target/16407, a mips64-elf regression from 3.0.4.
The problem is that for code like:

    struct s { char c1, c2; };
    void foo (struct s s)
    {
      static struct s s1;
      s1 = s;
    }
    int main ()
    {
      static struct s s2;
      foo (s2);
      exit (0);
    }

s1 and s2 are expected to have word alignment, but are being
emmitted using:

        .lcomm  s1.0,2
        .lcomm  s2.0,2

which guarantees no such thing.  This has long been the case,
but gcc 3.0.4 and earlier didn't take advantage of the extra
alignment, whereas gcc 3.2.3 and above do.

The best way of fixing this would probably be to use the elfos.h
definition of ASM_OUTPUT_ALIGNED_LOCAL, at least for gas.  I'm not
comfortable making that sort of change on a release branch though,
so the patch below simply applies the same technique that we use
for .comm in cases where .comm doesn't take an extra alignment.

I hope to revisit this whole area if we do decide to require gas
for 3.5.0.

Tested on mips-sgi-irix6.5, mips64-elf and mips64el-linux-gnu.
Applied to trunk and 3.4 branch.

Richard


	PR target/16407
	* config/mips/mips-protos.h (mips_declare_common_object): Declare.
	* config/mips/mips.c (mips_declare_common_object): New function,
	mostly split out from...
	(mips_output_aligned_decl_common): ...here.
	* config/mips/mips.h (ASM_OUTPUT_LOCAL): Remove in favor of...
	(ASM_OUTPUT_ALIGNED_LOCAL): ...this new definition.
	* config/mips/iris6.h (ASM_OUTPUT_ALIGNED_LOCAL): Undefine this
	rather than ASM_OUTPUT_LOCAL.  Call mips_declare_common_object.

testsuite/
	* gcc.c-torture/execute/20040707-1.c: New test.

Index: config/mips/mips-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips-protos.h,v
retrieving revision 1.59.4.3
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.59.4.3 mips-protos.h
*** config/mips/mips-protos.h	12 Feb 2004 19:10:13 -0000	1.59.4.3
--- config/mips/mips-protos.h	7 Jul 2004 12:35:55 -0000
*************** extern void mips_output_aligned_bss (FIL
*** 109,114 ****
--- 109,117 ----
  extern void mips_output_aligned_decl_common (FILE *, tree, const char *,
  					     unsigned HOST_WIDE_INT,
  					     unsigned int);
+ extern void mips_declare_common_object (FILE *, const char *,
+ 					const char *, unsigned HOST_WIDE_INT,
+ 					unsigned int, bool);
  extern void mips_declare_object (FILE *, const char *, const char *,
  				 const char *, ...);
  extern void mips_declare_object_name (FILE *, const char *, tree);
Index: config/mips/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.310.4.6
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.310.4.6 mips.h
*** config/mips/mips.h	11 Mar 2004 21:52:33 -0000	1.310.4.6
--- config/mips/mips.h	7 Jul 2004 12:35:56 -0000
*************** #define ASM_OUTPUT_ALIGNED_DECL_COMMON m
*** 3213,3221 ****
  /* This says how to define a local common symbol (ie, not visible to
     linker).  */
  
! #define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED)			\
!   mips_declare_object (STREAM, NAME, "\n\t.lcomm\t", ",%u\n", (int)(SIZE))
! 
  
  /* This says how to output an external.  It would be possible not to
     output anything and let undefined symbol become external. However
--- 3213,3222 ----
  /* This says how to define a local common symbol (ie, not visible to
     linker).  */
  
! #ifndef ASM_OUTPUT_ALIGNED_LOCAL
! #define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN) \
!   mips_declare_common_object (STREAM, NAME, "\n\t.lcomm\t", SIZE, ALIGN, false)
! #endif
  
  /* This says how to output an external.  It would be possible not to
     output anything and let undefined symbol become external. However
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.362.4.15
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.362.4.15 mips.c
*** config/mips/mips.c	7 Jul 2004 06:32:24 -0000	1.362.4.15
--- config/mips/mips.c	7 Jul 2004 12:35:59 -0000
*************** mips_output_aligned_decl_common (FILE *s
*** 6029,6045 ****
  			   ":\n\t.space\t" HOST_WIDE_INT_PRINT_UNSIGNED "\n",
  			   size);
      }
!   else if (TARGET_SGI_O32_AS)
      {
-       /* The SGI o32 assembler doesn't accept an alignment, so round up
- 	 the size instead.  */
        size += (align / BITS_PER_UNIT) - 1;
        size -= size % (align / BITS_PER_UNIT);
!       mips_declare_object (stream, name, "\n\t.comm\t",
  			   "," HOST_WIDE_INT_PRINT_UNSIGNED "\n", size);
      }
    else
!     mips_declare_object (stream, name, "\n\t.comm\t",
  			 "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n",
  			 size, align / BITS_PER_UNIT);
  }
--- 6029,6060 ----
  			   ":\n\t.space\t" HOST_WIDE_INT_PRINT_UNSIGNED "\n",
  			   size);
      }
!   else
!     /* The SGI o32 assembler doesn't accept an alignment.  */
!     mips_declare_common_object (stream, name, "\n\t.comm\t",
! 				size, align, !TARGET_SGI_O32_AS);
! }
! 
! /* Declare a common object of SIZE bytes using asm directive INIT_STRING.
!    NAME is the name of the object and ALIGN is the required alignment
!    in bytes.  TAKES_ALIGNMENT_P is true if the directive takes a third
!    alignment argument.  */
! 
! void
! mips_declare_common_object (FILE *stream, const char *name,
! 			    const char *init_string,
! 			    unsigned HOST_WIDE_INT size,
! 			    unsigned int align, bool takes_alignment_p)
! {
!   if (!takes_alignment_p)
      {
        size += (align / BITS_PER_UNIT) - 1;
        size -= size % (align / BITS_PER_UNIT);
!       mips_declare_object (stream, name, init_string,
  			   "," HOST_WIDE_INT_PRINT_UNSIGNED "\n", size);
      }
    else
!     mips_declare_object (stream, name, init_string,
  			 "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n",
  			 size, align / BITS_PER_UNIT);
  }
Index: config/mips/iris6.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/iris6.h,v
retrieving revision 1.74.4.3
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.74.4.3 iris6.h
*** config/mips/iris6.h	17 Feb 2004 20:46:45 -0000	1.74.4.3
--- config/mips/iris6.h	7 Jul 2004 12:35:59 -0000
*************** do								\
*** 357,363 ****
  while (0)
  
  /* ??? SGI assembler gives warning whenever .lcomm is used.  */
! #undef ASM_OUTPUT_LOCAL
  #define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN)		   \
  do									   \
    {									   \
--- 357,363 ----
  while (0)
  
  /* ??? SGI assembler gives warning whenever .lcomm is used.  */
! #undef ASM_OUTPUT_ALIGNED_LOCAL
  #define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN)		   \
  do									   \
    {									   \
*************** do									   \
*** 369,375 ****
  	ASM_OUTPUT_SKIP (STREAM, SIZE);					   \
        }									   \
      else								   \
!       mips_declare_object (STREAM, NAME, "\n\t.lcomm\t", ",%u\n", (int)(SIZE)); \
    }									   \
  while (0)
  
--- 369,376 ----
  	ASM_OUTPUT_SKIP (STREAM, SIZE);					   \
        }									   \
      else								   \
!       mips_declare_common_object (STREAM, NAME, "\n\t.lcomm\t",		   \
! 				  SIZE, ALIGN, false);			   \
    }									   \
  while (0)
  
*** /dev/null	Fri Apr 23 00:21:55 2004
--- testsuite/gcc.c-torture/execute/20040707-1.c	Wed Jul  7 13:35:11 2004
***************
*** 0 ****
--- 1,12 ----
+ struct s { char c1, c2; };
+ void foo (struct s s)
+ {
+   static struct s s1;
+   s1 = s;
+ }
+ int main ()
+ {
+   static struct s s2;
+   foo (s2);
+   exit (0);
+ }


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