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 E500 complex double va_arg


This patch fixes va_arg for _Complex double for E500.  _Complex double
is passed in four registers, 32 bits each, not necessarily aligned to
an even register pair (unlike 2-register types such as double which
are aligned to even pairs), so may only be 4-byte-aligned in the
register save area, so cannot simply be loaded from there with a
pointer dereference.  I've fixed this by using much the same code as
SPARC uses to make such an unaligned load via a temporary.

Tested with no regressions with cross to powerpc-none-linux-gnuspe
--enable-e500_double, mainline, 4.2 and 4.1.  OK to commit to mainline,
4.2, 4.1?

This fixes the following test failures:

FAIL: gcc.dg/compat/scalar-by-value-3 c_compat_x_tst.o-c_compat_y_tst.o execute
FAIL: gcc.dg/compat/scalar-return-3 c_compat_x_tst.o-c_compat_y_tst.o execute

2006-11-24  Joseph Myers  <joseph@codesourcery.com>

	* config/rs6000/rs6000.c (rs6000_gimplify_va_arg): If
	STRICT_ALIGNMENT and the type is more aligned than the saved
	registers, copy via a temporary.

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 119154)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -5963,6 +5965,27 @@
       append_to_statement_list (t, pre_p);
     }
 
+  if (STRICT_ALIGNMENT
+      && (TYPE_ALIGN (type)
+	  > (unsigned) BITS_PER_UNIT * (align < 4 ? 4 : align)))
+    {
+      /* The value (of type complex double, for example) may not be
+	 aligned in memory in the saved registers, so copy via a
+	 temporary.  (This is the same code as used for SPARC.)  */
+      tree tmp = create_tmp_var (type, "va_arg_tmp");
+      tree dest_addr = build_fold_addr_expr (tmp);
+
+      tree copy = build_function_call_expr
+	(implicit_built_in_decls[BUILT_IN_MEMCPY],
+	 tree_cons (NULL_TREE, dest_addr,
+		    tree_cons (NULL_TREE, addr,
+			       tree_cons (NULL_TREE, size_int (rsize * 4),
+					  NULL_TREE))));
+
+      gimplify_and_add (copy, pre_p);
+      addr = dest_addr;
+    }
+
   addr = fold_convert (ptrtype, addr);
   return build_va_arg_indirect_ref (addr);
 }

-- 
Joseph S. Myers
joseph@codesourcery.com


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