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
