fix 128-bit division. gcc mangled arguments when passing to the
authormartynas <martynas@openbsd.org>
Wed, 27 Aug 2008 00:31:01 +0000 (00:31 +0000)
committermartynas <martynas@openbsd.org>
Wed, 27 Aug 2008 00:31:01 +0000 (00:31 +0000)
__udivti3, because MUST_PASS_IN_STACK always returned 1 on amd64;
pr#5780
reported by Simon Kuhnle
tested by Simon Kuhnle, sthen@, brad@
double-checked & tweak from miod@
ok sthen@, brad@

gnu/usr.bin/gcc/gcc/calls.c
gnu/usr.bin/gcc/gcc/config/i386/i386-protos.h
gnu/usr.bin/gcc/gcc/config/i386/i386.c
gnu/usr.bin/gcc/gcc/config/i386/i386.h
gnu/usr.bin/gcc/gcc/expr.h

index 8c3ad6e..fb9d3a2 100644 (file)
@@ -4694,3 +4694,45 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
 
   return sibcall_failure;
 }
+
+/* Nonzero if we do not know how to pass TYPE solely in registers.
+   We cannot do so in the following cases:
+
+   - if the type has variable size
+   - if the type is marked as addressable (it is required to be constructed
+     into the stack)
+   - if the padding and mode of the type is such that a copy into a register
+     would put it into the wrong part of the register.
+
+   Which padding can't be supported depends on the byte endianness.
+
+   A value in a register is implicitly padded at the most significant end.
+   On a big-endian machine, that is the lower end in memory.
+   So a value padded in memory at the upper end can't go in a register.
+   For a little-endian machine, the reverse is true.  */
+
+bool
+default_must_pass_in_stack (enum machine_mode mode, tree type)
+{
+  if (!type)
+    return false;
+
+  /* If the type has variable size...  */
+  if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+    return true;
+
+  /* If the type is marked as addressable (it is required
+     to be constructed into the stack)...  */
+  if (TREE_ADDRESSABLE (type))
+    return true;
+
+  /* If the padding and mode of the type is such that a copy into
+     a register would put it into the wrong part of the register.  */
+  if (mode == BLKmode
+      && int_size_in_bytes (type) % (PARM_BOUNDARY / BITS_PER_UNIT)
+      && (FUNCTION_ARG_PADDING (mode, type)
+         == (BYTES_BIG_ENDIAN ? upward : downward)))
+    return true;
+
+  return false;
+}
index b5ddb37..1c1d650 100644 (file)
@@ -221,6 +221,7 @@ extern int x86_field_alignment PARAMS ((tree, int));
 
 extern rtx ix86_tls_get_addr PARAMS ((void));
 extern void x86_machine_dependent_reorg PARAMS ((rtx));
+extern bool ix86_must_pass_in_stack PARAMS ((enum machine_mode mode, tree));
 
 /* In winnt.c  */
 extern int i386_pe_dllexport_name_p PARAMS ((const char *));
index ba0b78c..a94bc41 100644 (file)
@@ -1727,6 +1727,10 @@ classify_argument (mode, type, classes, bit_offset)
   if (bytes < 0)
     return 0;
 
+  if (mode != VOIDmode
+      && MUST_PASS_IN_STACK (mode, type))
+    return 0;
+
   if (type && AGGREGATE_TYPE_P (type))
     {
       int i;
@@ -14812,4 +14816,15 @@ x86_machine_dependent_reorg (first)
   }
 }
 
+/* Return if we do not know how to pass TYPE solely in registers.  */
+bool
+ix86_must_pass_in_stack (mode, type)
+       enum machine_mode mode;
+       tree type;
+{
+   if (default_must_pass_in_stack (mode, type))
+     return true;
+   return (!TARGET_64BIT && type && mode == TImode);
+}
+
 #include "gt-i386.h"
index 796b48b..f8d521d 100644 (file)
@@ -1638,18 +1638,7 @@ enum reg_class
    definition that is usually appropriate, refer to expr.h for additional
    documentation. If `REG_PARM_STACK_SPACE' is defined, the argument will be
    computed in the stack and then loaded into a register.  */
-#define MUST_PASS_IN_STACK(MODE, TYPE)                         \
-  ((TYPE) != 0                                                 \
-   && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST             \
-       || TREE_ADDRESSABLE (TYPE)                              \
-       || ((MODE) == TImode)                                   \
-       || ((MODE) == BLKmode                                   \
-          && ! ((TYPE) != 0                                    \
-                && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
-                && 0 == (int_size_in_bytes (TYPE)              \
-                         % (PARM_BOUNDARY / BITS_PER_UNIT)))   \
-          && (FUNCTION_ARG_PADDING (MODE, TYPE)                \
-              == (BYTES_BIG_ENDIAN ? upward : downward)))))
+#define MUST_PASS_IN_STACK(MODE, TYPE) ix86_must_pass_in_stack ((MODE), (TYPE))
 
 /* Value is the number of bytes of arguments automatically
    popped when returning from a subroutine call.
index c38cd99..c6b1e23 100644 (file)
@@ -159,34 +159,9 @@ enum direction {none, upward, downward};  /* Value has this type.  */
 #define PRETEND_OUTGOING_VARARGS_NAMED 0
 #endif
 
-/* Nonzero if we do not know how to pass TYPE solely in registers.
-   We cannot do so in the following cases:
-
-   - if the type has variable size
-   - if the type is marked as addressable (it is required to be constructed
-     into the stack)
-   - if the padding and mode of the type is such that a copy into a register
-     would put it into the wrong part of the register.
-
-   Which padding can't be supported depends on the byte endianness.
-
-   A value in a register is implicitly padded at the most significant end.
-   On a big-endian machine, that is the lower end in memory.
-   So a value padded in memory at the upper end can't go in a register.
-   For a little-endian machine, the reverse is true.  */
-
-#ifndef MUST_PASS_IN_STACK
-#define MUST_PASS_IN_STACK(MODE,TYPE)                  \
-  ((TYPE) != 0                                         \
-   && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST     \
-       || TREE_ADDRESSABLE (TYPE)                      \
-       || ((MODE) == BLKmode                           \
-          && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
-                && 0 == (int_size_in_bytes (TYPE)      \
-                         % (PARM_BOUNDARY / BITS_PER_UNIT))) \
-          && (FUNCTION_ARG_PADDING (MODE, TYPE)        \
-              == (BYTES_BIG_ENDIAN ? upward : downward)))))
-#endif
+/* Nonzero if we do not know how to pass TYPE solely in registers.  */
+extern bool default_must_pass_in_stack PARAMS((enum machine_mode, tree));
+#define MUST_PASS_IN_STACK(MODE,TYPE) default_must_pass_in_stack(MODE, TYPE)
 
 /* Nonzero if type TYPE should be returned in memory.
    Most machines can use the following default definition.  */