On Sun, May 17, 2026 at 7:57 PM oltolm <[email protected]> wrote:
>
> 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* } } } */

Remove { target { x86_64-*-mingw* } }.

> +/* { dg-options "-O2 -msse2 -mno-apxf" } */

Add -mabi=ms instead.

> +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } } } */

{ target lp64 }

> +
> +/*
> +**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);
> +}

Please also test -mabi=ms with sysv_abi attribute and -mabi=sysv
with ms_abi attribute.

> 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

I don't think this change is required.  You can use

**...

to skip unrelated lines.

> @@ -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
>


-- 
H.J.

Reply via email to