From: Oleg Tolmatcev <[email protected]>

The preserve_none calling convention uses the six-register preserve_none 
integer parameter set even when the default ABI is MS. Update argument register 
recognition, cumulative argument setup, and argument lowering so preserve_none 
calls on x86_64 MinGW use the generic 64-bit path rather than the plain MS ABI 
path.

Add MinGW compile tests for integer argument remapping and sibling-call 
behavior.
Update scanasm matching for MinGW.

gcc/config/i386/ChangeLog:

* i386.cc (ix86_function_arg_regno_p): Use six integer argument
registers for preserve_none under the MS ABI.
(init_cumulative_args): Likewise.
(ix86_function_arg): Route preserve_none calls through
function_arg_64.

gcc/testsuite/ChangeLog:

* gcc.target/i386/preserve-none-31.c: New test.
* gcc.target/i386/preserve-none-32.c: New test.
* lib/scanasm.exp (configure_check-function-bodies): Handle x86_64
MinGW end markers and instruction indentation.

Signed-off-by: oltolm <[email protected]>
---
 gcc/config/i386/i386.cc                       | 19 +++++++-----
 .../gcc.target/i386/preserve-none-31.c        | 30 +++++++++++++++++++
 .../gcc.target/i386/preserve-none-32.c        | 24 +++++++++++++++
 gcc/testsuite/lib/scanasm.exp                 | 16 ++++++----
 4 files changed, 76 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-31.c
 create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-32.c

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 2744c74957..9bb6b6001c 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -1609,8 +1609,13 @@ ix86_function_arg_regno_p (int regno)
   else
     parm_regs = x86_64_int_parameter_registers;
 
-  for (i = 0; i < (call_abi == MS_ABI
-                  ? X86_64_MS_REGPARM_MAX : X86_64_REGPARM_MAX); i++)
+  int regparm_max
+    = (call_abi == MS_ABI
+       && !(cfun && cfun->machine->call_saved_registers == TYPE_PRESERVE_NONE))
+       ? X86_64_MS_REGPARM_MAX
+       : X86_64_REGPARM_MAX;
+
+  for (i = 0; i < regparm_max; i++)
     if (regno == parm_regs[i])
       return true;
   return false;
@@ -1920,9 +1925,9 @@ init_cumulative_args (CUMULATIVE_ARGS *cum,  /* Argument 
info to initialize */
   cum->nregs = ix86_regparm;
   if (TARGET_64BIT)
     {
-      cum->nregs = (cum->call_abi == SYSV_ABI
-                   ? X86_64_REGPARM_MAX
-                   : X86_64_MS_REGPARM_MAX);
+      cum->nregs = (cum->preserve_none_abi || cum->call_abi == SYSV_ABI
+                  ? X86_64_REGPARM_MAX
+                  : X86_64_MS_REGPARM_MAX);
     }
   if (TARGET_SSE)
     {
@@ -3273,7 +3278,7 @@ ix86_function_arg_advance (cumulative_args_t cum_v,
     {
       enum calling_abi call_abi = cum ? cum->call_abi : ix86_abi;
 
-      if (call_abi == MS_ABI)
+      if (call_abi == MS_ABI && !(cum && cum->preserve_none_abi))
        nregs = function_arg_advance_ms_64 (cum, bytes, words);
       else
        nregs = function_arg_advance_64 (cum, mode, arg.type, words,
@@ -3604,7 +3609,7 @@ ix86_function_arg (cumulative_args_t cum_v, const 
function_arg_info &arg)
     {
       enum calling_abi call_abi = cum ? cum->call_abi : ix86_abi;
 
-      if (call_abi == MS_ABI)
+      if (call_abi == MS_ABI && !(cum && cum->preserve_none_abi))
        reg = function_arg_ms_64 (cum, mode, arg.mode, arg.named,
                                  arg.type, bytes);
       else
diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-31.c 
b/gcc/testsuite/gcc.target/i386/preserve-none-31.c
new file mode 100644
index 0000000000..d8ab38cdba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/preserve-none-31.c
@@ -0,0 +1,30 @@
+/* { dg-do compile { target { x86_64-*-mingw* } } } */
+/* { dg-options "-O2 -msse2 -mno-apxf" } */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } } } */
+
+/*
+**entry:
+**     subq    \$72, %rsp
+**     xorl    %eax, %eax
+**     movl    120\(%rsp\), %esi
+**     movl    112\(%rsp\), %edi
+**     movl    %ecx, %r12d
+**     movl    %edx, %r13d
+**     movl    %r9d, %r15d
+**     movl    %r8d, %r14d
+**     movl    \$-559038737, 48\(%rsp\)
+**     call    continuation
+**     nop
+**     addq    \$72, %rsp
+**     ret
+*/
+
+extern void continuation (int, int, int, int, int, int, ...)
+  __attribute__ ((preserve_none));
+
+__attribute__ ((no_callee_saved_registers))
+void
+entry (int arg1, int arg2, int arg3, int arg4, int arg5, int arg6)
+{
+  continuation (arg1, arg2, arg3, arg4, arg5, arg6, 0xdeadbeef);
+}
diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-32.c 
b/gcc/testsuite/gcc.target/i386/preserve-none-32.c
new file mode 100644
index 0000000000..8a2173b413
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/preserve-none-32.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { target { x86_64-*-mingw* } } } */
+/* { dg-options "-O2 -msse2 -mno-apxf" } */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } } } */
+
+/*
+**entry:
+**     movl    56\(%rsp\), %esi
+**     movl    48\(%rsp\), %edi
+**     movl    40\(%rsp\), %r15d
+**     movl    %edx, %r12d
+**     movl    %r9d, %r14d
+**     movl    %r8d, %r13d
+**     jmp     continuation
+*/
+
+extern void continuation (double, int, int, int, int, int, int)
+  __attribute__ ((preserve_none));
+
+__attribute__ ((no_callee_saved_registers))
+void
+entry (double fp, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6)
+{
+  continuation (fp, arg1, arg2, arg3, arg4, arg5, arg6);
+}
diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index abfdd6a3a1..52f03e4412 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -4,12 +4,12 @@
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 3 of the License, or
 # (at your option) any later version.
-# 
+#
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License
 # along with GCC; see the file COPYING3.  If not see
 # <http://www.gnu.org/licenses/>.
@@ -138,7 +138,7 @@ proc scan-assembler-not { args } {
 
 set_required_options_for scan-assembler-not
 
-# Return the scan for the assembly for hidden visibility. 
+# Return the scan for the assembly for hidden visibility.
 
 proc hidden-scan-for { symbol } {
 
@@ -563,7 +563,7 @@ proc scan-assembler-times { args } {
 
 set_required_options_for scan-assembler-times
 
-# Call pass if pattern is present within a lower or upper bound, 
+# Call pass if pattern is present within a lower or upper bound,
 # otherwise fail.
 # ex /* { dg-final { scan-assembler-bound {RE} > 3 } }
 proc scan-assembler-bound { args } {
@@ -610,7 +610,7 @@ proc scan-assembler-bound { args } {
         error "scan-assembler-bound: illegal argument: $bound"
         return
     }
-    
+
     set fd [open $output_file r]
     set text [read $fd]
     close $fd
@@ -932,7 +932,8 @@ proc configure_check-function-bodies { config } {
        set up_config(end) {^\}$}
     } elseif { [istarget *-*-darwin*] } {
        set up_config(end) {^LFE[0-9]+}
-    } elseif { [istarget aarch64*-*-mingw32] } {
+    } elseif { [istarget aarch64*-*-mingw32]
+              || [istarget x86_64*-*-mingw*] } {
        set up_config(end) {seh_endproc}
     } else {
        set up_config(end) {^\s*\.size}
@@ -964,6 +965,9 @@ proc configure_check-function-bodies { config } {
        # any whitespace prefixed, and we'd like to be able to match these,
        # too.  We thereare expect any amount of whitespace here.
        set up_config(line_prefix) {\t*}
+    } elseif { [istarget *-*-mingw*] } {
+       # MinGW assemblers may indent instructions with spaces rather than tabs.
+       set up_config(line_prefix) {[ \t]+}
     } else {
        set up_config(line_prefix) {\t}
     }
-- 
2.54.0.windows.1

Reply via email to