This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, i386]: Partially fix PR 38151
- From: Uros Bizjak <ubizjak at gmail dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 19 Nov 2008 22:06:41 +0100
- Subject: [PATCH, i386]: Partially fix PR 38151
Hello!
There is a problem with x86_64 merged argument passing when agregates
are involved. The problem is, that we don't account for cases, where
argument register crosses argument register boundary, i.e. when merging
32bit and 64bit values.
classify_argument () function should return classes for both parts since
the second value is now passed in two registers.
2008-11-19 Uros Bizjak <ubizjak@gmail.com>
PR target/38151
* config/i386/i386.c (classify_argument) [integer mode size <= 64bit]:
Handle cases when integer argument crosses argument register boundary.
testsuite/ChangeLog:
2008-11-19 Uros Bizjak <ubizjak@gmail.com>
PR target/38151
* gcc.target/i386/pr38151-1.c: New test.
Attached patch was bootstrapped and regression tested on
x86_64-pc-linux-gnu {,-m32}. The patch is however not enough to fully
fix the PR, since the problem remains for va_arg arguments. Will look
tomorrow.
Uros.
Index: testsuite/gcc.target/i386/pr38151-1.c
===================================================================
--- testsuite/gcc.target/i386/pr38151-1.c (revision 0)
+++ testsuite/gcc.target/i386/pr38151-1.c (revision 0)
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+void abort (void);
+
+struct S2848
+{
+ unsigned int a;
+ _Complex int b;
+};
+
+struct S2848 s2848;
+
+void __attribute__((noinline))
+check2848 (struct S2848 arg0)
+{
+ if (arg0.b != s2848.b)
+ abort ();
+}
+
+int main()
+{
+ s2848.a = 4027477739U;
+ s2848.b = (723419448 + -218144346 * __extension__ 1i);
+
+ check2848 (s2848);
+
+ return 0;
+}
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c (revision 142014)
+++ config/i386/i386.c (working copy)
@@ -5029,11 +5029,33 @@ classify_argument (enum machine_mode mod
case CSImode:
case CHImode:
case CQImode:
- if (bit_offset + GET_MODE_BITSIZE (mode) <= 32)
- classes[0] = X86_64_INTEGERSI_CLASS;
- else
- classes[0] = X86_64_INTEGER_CLASS;
- return 1;
+ {
+ int size = (bit_offset % 64)+ (int) GET_MODE_BITSIZE (mode);
+
+ if (size <= 32)
+ {
+ classes[0] = X86_64_INTEGERSI_CLASS;
+ return 1;
+ }
+ else if (size <= 64)
+ {
+ classes[0] = X86_64_INTEGER_CLASS;
+ return 1;
+ }
+ else if (size <= 64+32)
+ {
+ classes[0] = X86_64_INTEGER_CLASS;
+ classes[1] = X86_64_INTEGERSI_CLASS;
+ return 2;
+ }
+ else if (size <= 64+64)
+ {
+ classes[0] = classes[1] = X86_64_INTEGER_CLASS;
+ return 2;
+ }
+ else
+ gcc_unreachable ();
+ }
case CDImode:
case TImode:
classes[0] = classes[1] = X86_64_INTEGER_CLASS;