On Mon, May 18, 2026 at 7:09 AM Andrew Pinski
<[email protected]> wrote:
>
> On Sun, May 17, 2026 at 3:56 PM H.J. Lu <[email protected]> wrote:
> >
> > On Mon, May 18, 2026 at 6:21 AM H.J. Lu <[email protected]> wrote:
> > >
> > > 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* } }.
> >
> > Please use { target lp64 }.
> >
> > > > +/* { dg-options "-O2 -msse2 -mno-apxf" } */
> > >
> > > Add -mabi=ms instead.
> > >
> > > > +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } }
> > > > } */
> > >
> > > { target lp64 }
>
> Actually I think lp64 should be !ia32. The reason is x86_64-mingw is a
> LLP64L32 target so lp64 won't match here.
It should be
/* { dg-do compile { target { lp64 || llp64 } } } */
BTW, this test crashed on Linux/x86-64:
[hjl@gnu-tgl-3 gcc]$ cat /tmp/x.c
extern void continuation (double, int, int, int, int, int, int)
__attribute__ ((preserve_none));
__attribute__ ((no_callee_saved_registers, sysv_abi))
void
entry (double fp, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6)
{
continuation (fp, arg1, arg2, arg3, arg4, arg5, arg6);
}
[hjl@gnu-tgl-3 gcc]$ ./xgcc -B./ -O2 -S -mabi=ms -mtune=generic /tmp/x.c
during RTL pass: expand
/tmp/x.c: In function ‘entry’:
/tmp/x.c:8:3: internal compiler error: in expand_call, at calls.cc:3763
8 | continuation (fp, arg1, arg2, arg3, arg4, arg5, arg6);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0x48b4190 internal_error(char const*, ...)
/export/gnu/import/git/gitlab/x86-gcc/gcc/diagnostic-global-context.cc:787
0x48c2a83 fancy_abort(char const*, int, char const*)
/export/gnu/import/git/gitlab/x86-gcc/gcc/diagnostics/context.cc:1813
0x2185a09 expand_call(tree_node*, rtx_def*, int)
/export/gnu/import/git/gitlab/x86-gcc/gcc/calls.cc:3763
0x237d8d3 expand_expr_real_1(tree_node*, rtx_def*, machine_mode,
expand_modifier, rtx_def**, bool)
/export/gnu/import/git/gitlab/x86-gcc/gcc/expr.cc:12677
0x236e1a1 expand_expr_real(tree_node*, rtx_def*, machine_mode,
expand_modifier, rtx_def**, bool)
/export/gnu/import/git/gitlab/x86-gcc/gcc/expr.cc:9618
0x2173c68 expand_expr(tree_node*, rtx_def*, machine_mode, expand_modifier)
/export/gnu/import/git/gitlab/x86-gcc/gcc/expr.h:323
0x21a51af expand_call_stmt
/export/gnu/import/git/gitlab/x86-gcc/gcc/cfgexpand.cc:3205
0x21a8e0a expand_gimple_stmt_1
/export/gnu/import/git/gitlab/x86-gcc/gcc/cfgexpand.cc:4243
0x21a9440 expand_gimple_stmt
/export/gnu/import/git/gitlab/x86-gcc/gcc/cfgexpand.cc:4390
0x21a956b expand_gimple_tailcall
/export/gnu/import/git/gitlab/x86-gcc/gcc/cfgexpand.cc:4437
0x21b206e expand_gimple_basic_block
/export/gnu/import/git/gitlab/x86-gcc/gcc/cfgexpand.cc:6480
0x21b480c execute
/export/gnu/import/git/gitlab/x86-gcc/gcc/cfgexpand.cc:7254
./cc1 -quiet -iprefix
/export/build/gnu/tools-build/gcc-gitlab-debug/build-x86_64-linux/gcc/../lib/gcc/x86_64-pc-linux-gnu/17.0.0/
-isystem ./include -isystem ./include-fixed /tmp/x.c -quiet -dumpbase
x.c -dumpbase-ext .c -mabi=ms -mtune=generic -march=x86-64
-mtls-dialect=gnu2 -O2 -o x.s
Please submit a full bug report, with preprocessed source (by using
-freport-bug).
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
[hjl@gnu-tgl-3 gcc]$
The fix should be done after
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124798
has been fixed.
> Thanks,
> Andrew
>
> > >
> > > > +
> > > > +/*
> > > > +**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.
> >
> >
> >
> > --
> > H.J.
--
H.J.