In 64-bit mode, preserve_none attribute uses a different calling convention. Ignore MS ABI with preserve_none attribute to always use the preserve_none calling convention with preserve_none attribute.
gcc/ PR target/125297 * config/i386/i386.cc (ix86_function_arg_regno_p): Use x86_64_preserve_none_int_parameter_registers for TYPE_PRESERVE_NONE. (ix86_function_type_abi): In 64-bit mode, ignore ms_abi attribute with preserve_none attribute. (x86_64_cumulative_ms_abi_p): New function. (init_cumulative_args): Call x86_64_cumulative_ms_abi_p to decide if MS_ABI is used. (ix86_function_arg_advance): Likewise. (ix86_function_arg): Likewise. gcc/testsuite/ PR target/125297 * gcc.target/i386/preserve-none-31a.c: New test. * gcc.target/i386/preserve-none-31b.c: Likewise. * gcc.target/i386/preserve-none-32a.c: Likewise. * gcc.target/i386/preserve-none-32b.c: Likewise. * gcc.target/i386/preserve-none-33a.c: Likewise. * gcc.target/i386/preserve-none-33b.c: Likewise. * gcc.target/i386/preserve-none-34a.c: Likewise. * gcc.target/i386/preserve-none-34b.c: Likewise. -- H.J.
From 930551bb624e397594d2d59e1f82bfc86caebd22 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <[email protected]> Date: Wed, 13 May 2026 08:27:50 +0800 Subject: [PATCH] x86: Honor preserve_none ABI for x86-64 MS calls In 64-bit mode, preserve_none attribute uses a different calling convention. Ignore MS ABI with preserve_none attribute to always use the preserve_none calling convention with preserve_none attribute. gcc/ PR target/125297 * config/i386/i386.cc (ix86_function_arg_regno_p): Use x86_64_preserve_none_int_parameter_registers for TYPE_PRESERVE_NONE. (ix86_function_type_abi): In 64-bit mode, ignore ms_abi attribute with preserve_none attribute. (x86_64_cumulative_ms_abi_p): New function. (init_cumulative_args): Call x86_64_cumulative_ms_abi_p to decide if MS_ABI is used. (ix86_function_arg_advance): Likewise. (ix86_function_arg): Likewise. gcc/testsuite/ PR target/125297 * gcc.target/i386/preserve-none-31a.c: New test. * gcc.target/i386/preserve-none-31b.c: Likewise. * gcc.target/i386/preserve-none-32a.c: Likewise. * gcc.target/i386/preserve-none-32b.c: Likewise. * gcc.target/i386/preserve-none-33a.c: Likewise. * gcc.target/i386/preserve-none-33b.c: Likewise. * gcc.target/i386/preserve-none-34a.c: Likewise. * gcc.target/i386/preserve-none-34b.c: Likewise. Signed-off-by: H.J. Lu <[email protected]> --- gcc/config/i386/i386.cc | 38 +++++++++++++------ .../gcc.target/i386/preserve-none-31a.c | 36 ++++++++++++++++++ .../gcc.target/i386/preserve-none-31b.c | 25 ++++++++++++ .../gcc.target/i386/preserve-none-32a.c | 29 ++++++++++++++ .../gcc.target/i386/preserve-none-32b.c | 18 +++++++++ .../gcc.target/i386/preserve-none-33a.c | 36 ++++++++++++++++++ .../gcc.target/i386/preserve-none-33b.c | 25 ++++++++++++ .../gcc.target/i386/preserve-none-34a.c | 29 ++++++++++++++ .../gcc.target/i386/preserve-none-34b.c | 18 +++++++++ 9 files changed, 243 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-31a.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-31b.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-32a.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-32b.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-33a.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-33b.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-34a.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-34b.c diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 23f65ab401d..ff9428ddcff 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -1591,16 +1591,19 @@ ix86_function_arg_regno_p (int regno) if (call_abi == SYSV_ABI && regno == AX_REG) return true; + int regparm_max = X86_64_REGPARM_MAX; if (cfun && cfun->machine->call_saved_registers == TYPE_PRESERVE_NONE) parm_regs = x86_64_preserve_none_int_parameter_registers; else if (call_abi == MS_ABI) - parm_regs = x86_64_ms_abi_int_parameter_registers; + { + parm_regs = x86_64_ms_abi_int_parameter_registers; + regparm_max = X86_64_MS_REGPARM_MAX; + } 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++) + for (i = 0; i < regparm_max; i++) if (regno == parm_regs[i]) return true; return false; @@ -1665,7 +1668,11 @@ ix86_function_type_abi (const_tree fntype) warned = 1; } - abi = MS_ABI; + /* NB: preserve_none attribute overrides ms_abi in 64-bit mode. */ + if (!TARGET_64BIT + || !lookup_attribute ("preserve_none", + TYPE_ATTRIBUTES (fntype))) + abi = MS_ABI; } else if (abi == MS_ABI && lookup_attribute ("sysv_abi", TYPE_ATTRIBUTES (fntype))) @@ -1856,6 +1863,17 @@ ix86_init_pic_reg (void) commit_one_edge_insertion (entry_edge); } +/* Return true if x86-64 CUM is MS_ABI. */ + +static bool +x86_64_cumulative_ms_abi_p (CUMULATIVE_ARGS *cum) +{ + if (!cum) + return ix86_abi == MS_ABI; + + return !cum->preserve_none_abi && cum->call_abi == MS_ABI; +} + /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is 0. */ @@ -1910,9 +1928,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 = (x86_64_cumulative_ms_abi_p (cum) + ? X86_64_MS_REGPARM_MAX + : X86_64_REGPARM_MAX); } if (TARGET_SSE) { @@ -3262,9 +3280,7 @@ ix86_function_arg_advance (cumulative_args_t cum_v, if (TARGET_64BIT) { - enum calling_abi call_abi = cum ? cum->call_abi : ix86_abi; - - if (call_abi == MS_ABI) + if (x86_64_cumulative_ms_abi_p (cum)) nregs = function_arg_advance_ms_64 (cum, bytes, words); else nregs = function_arg_advance_64 (cum, mode, arg.type, words, @@ -3593,7 +3609,7 @@ ix86_function_arg (cumulative_args_t cum_v, const function_arg_info &arg) if (TARGET_64BIT) { - if (cum->call_abi == MS_ABI) + if (x86_64_cumulative_ms_abi_p (cum)) 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-31a.c b/gcc/testsuite/gcc.target/i386/preserve-none-31a.c new file mode 100644 index 00000000000..b24499cfb8f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-31a.c @@ -0,0 +1,36 @@ +/* { dg-do compile { target { lp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic -mabi=ms" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** subq \$72, %rsp +**... +** movl %ecx, %r12d +** movl %edx, %r13d +** movl %r9d, %r15d +** movl 120\(%rsp\), %esi +** movl 112\(%rsp\), %edi +** movl %r8d, %r14d +** xorl %eax, %eax +** movl \$-559038737, 48\(%rsp\) +** call continuation +** addq \$72, %rsp +**... +** ret +** .cfi_endproc +**... +*/ + +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-31b.c b/gcc/testsuite/gcc.target/i386/preserve-none-31b.c new file mode 100644 index 00000000000..9b6ad95c36f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-31b.c @@ -0,0 +1,25 @@ +/* { dg-do compile { target { llp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic -mabi=ms" } */ +/* Keep labels and directives ('.seh_endprologue'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +** subq \$72, %rsp +** .seh_stackalloc 72 +** .seh_endprologue +** 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 +*/ + +#include "preserve-none-31a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-32a.c b/gcc/testsuite/gcc.target/i386/preserve-none-32a.c new file mode 100644 index 00000000000..1928491a4f2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-32a.c @@ -0,0 +1,29 @@ +/* { dg-do compile { target { lp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic -mabi=ms" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** movl 56\(%rsp\), %esi +** movl 48\(%rsp\), %edi +** movl %edx, %r12d +** movl %r9d, %r14d +** movl 40\(%rsp\), %r15d +** movl %r8d, %r13d +** jmp continuation +** .cfi_endproc +**... +*/ + +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/gcc.target/i386/preserve-none-32b.c b/gcc/testsuite/gcc.target/i386/preserve-none-32b.c new file mode 100644 index 00000000000..3de4322fef7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-32b.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { llp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic -mabi=ms" } */ +/* Keep labels and directives ('.seh_endprologue'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +** .seh_endprologue +** movl 56\(%rsp\), %esi +** movl 48\(%rsp\), %edi +** movl 40\(%rsp\), %r15d +** movl %edx, %r12d +** movl %r9d, %r14d +** movl %r8d, %r13d +** jmp continuation +*/ + +#include "preserve-none-32a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-33a.c b/gcc/testsuite/gcc.target/i386/preserve-none-33a.c new file mode 100644 index 00000000000..086df3681ec --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-33a.c @@ -0,0 +1,36 @@ +/* { dg-do compile { target { lp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic -mabi=sysv" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** subq \$24, %rsp +**... +** movl %edi, %r12d +** movl %esi, %r13d +** movl %edx, %r14d +** movl \$-559038737, \(%rsp\) +** movl %ecx, %r15d +** movl %r9d, %esi +** movl %r8d, %edi +** xorl %eax, %eax +** call continuation +** addq \$24, %rsp +**... +** ret +** .cfi_endproc +**... +*/ + +extern void continuation (int, int, int, int, int, int, ...) + __attribute__ ((preserve_none, ms_abi)); + +__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-33b.c b/gcc/testsuite/gcc.target/i386/preserve-none-33b.c new file mode 100644 index 00000000000..b82f790d645 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-33b.c @@ -0,0 +1,25 @@ +/* { dg-do compile { target { llp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic -mabi=ms" } */ +/* Keep labels and directives ('.seh_endprologue'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +** subq \$72, %rsp +** .seh_stackalloc 72 +** .seh_endprologue +** 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 +*/ + +#include "preserve-none-33a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-34a.c b/gcc/testsuite/gcc.target/i386/preserve-none-34a.c new file mode 100644 index 00000000000..dbc36e9a21b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-34a.c @@ -0,0 +1,29 @@ +/* { dg-do compile { target { lp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic -mabi=sysv" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** movl %edi, %r12d +** movl %esi, %r13d +** movl %edx, %r14d +** movl %ecx, %r15d +** movl %r9d, %esi +** movl %r8d, %edi +** jmp continuation +** .cfi_endproc +**... +*/ + +extern void continuation (double, int, int, int, int, int, int) + __attribute__ ((preserve_none, ms_abi)); + +__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/gcc.target/i386/preserve-none-34b.c b/gcc/testsuite/gcc.target/i386/preserve-none-34b.c new file mode 100644 index 00000000000..75323ad7863 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-34b.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { llp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic -mabi=ms" } */ +/* Keep labels and directives ('.seh_endprologue'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +** .seh_endprologue +** movl 56\(%rsp\), %esi +** movl 48\(%rsp\), %edi +** movl 40\(%rsp\), %r15d +** movl %edx, %r12d +** movl %r9d, %r14d +** movl %r8d, %r13d +** jmp continuation +*/ + +#include "preserve-none-34a.c" -- 2.55.0
