Use the function's abi instead of the target's abi when CUM is NULL and a
sysv_abi function is calling an ms_abi function or vice versa.
gcc/ChangeLog:
* config/i386/i386.cc (ix86_pass_by_reference): Use the function's
ABI instead of the target's ABI when CUM is NULL.
gcc/testsuite/ChangeLog:
* gcc.target/i386/va-arg-abi-attribute.c: New test.
Signed-off-by: Oleg Tolmatcev <[email protected]>
---
gcc/config/i386/i386.cc | 2 +-
.../gcc.target/i386/va-arg-abi-attribute.c | 39 +++++++++++++++++++
2 files changed, 40 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/i386/va-arg-abi-attribute.c
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index b09a507782..2b1c3ae13d 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -3664,7 +3664,7 @@ ix86_pass_by_reference (cumulative_args_t cum_v, const
function_arg_info &arg)
if (TARGET_64BIT)
{
- enum calling_abi call_abi = cum ? cum->call_abi : ix86_abi;
+ enum calling_abi call_abi = cum ? cum->call_abi : ix86_cfun_abi ();
/* See Windows x64 Software Convention. */
if (call_abi == MS_ABI)
diff --git a/gcc/testsuite/gcc.target/i386/va-arg-abi-attribute.c
b/gcc/testsuite/gcc.target/i386/va-arg-abi-attribute.c
new file mode 100644
index 0000000000..e0bb01b6b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/va-arg-abi-attribute.c
@@ -0,0 +1,39 @@
+/* va_arg must follow the convention of the function it is in: the MS one
+ passes a struct of more than eight bytes by reference, System V by
+ value. */
+/* { dg-do run { target { lp64 || llp64 } } } */
+/* { dg-options "-std=gnu99" } */
+
+struct s { long long a, b; };
+
+static __attribute__((sysv_abi, noipa)) long long
+sysv (int n, ...)
+{
+ __builtin_sysv_va_list ap;
+ struct s x;
+ __builtin_sysv_va_start (ap, n);
+ x = __builtin_va_arg (ap, struct s);
+ __builtin_sysv_va_end (ap);
+ return x.a * 10 + x.b;
+}
+
+static __attribute__((ms_abi, noipa)) long long
+ms (int n, ...)
+{
+ __builtin_ms_va_list ap;
+ struct s x;
+ __builtin_ms_va_start (ap, n);
+ x = __builtin_va_arg (ap, struct s);
+ __builtin_ms_va_end (ap);
+ return x.a * 10 + x.b;
+}
+
+int
+main (void)
+{
+ struct s x = { 3, 4 };
+
+ if (sysv (1, x) != 34 || ms (1, x) != 34)
+ __builtin_abort ();
+ return 0;
+}
--
2.55.0.windows.5