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. (ix86_pass_by_reference): Likewise. (ix86_setup_incoming_varargs): 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. * gcc.target/i386/preserve-none-35a.c: Likewise. * gcc.target/i386/preserve-none-35b.c: Likewise. * gcc.target/i386/preserve-none-35c.c: Likewise. * gcc.target/i386/preserve-none-35d.c: Likewise. * gcc.target/i386/preserve-none-35e.c: Likewise. * gcc.target/i386/preserve-none-35f.c: Likewise. * gcc.target/i386/preserve-none-35g.c: Likewise. * gcc.target/i386/preserve-none-36a.c: Likewise. * gcc.target/i386/preserve-none-36b.c: Likewise. * gcc.target/i386/preserve-none-36c.c: Likewise. * gcc.target/i386/preserve-none-36d.c: Likewise. * gcc.target/i386/preserve-none-36e.c: Likewise. * gcc.target/i386/preserve-none-36f.c: Likewise. * gcc.target/i386/preserve-none-36g.c: Likewise. -- H.J.
From c5746ea0de6b525b06cd59f2c80fbc9740649f52 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <[email protected]> Date: Wed, 13 May 2026 08:27:50 +0800 Subject: [PATCH v2] 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. (ix86_pass_by_reference): Likewise. (ix86_setup_incoming_varargs): 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. * gcc.target/i386/preserve-none-35a.c: Likewise. * gcc.target/i386/preserve-none-35b.c: Likewise. * gcc.target/i386/preserve-none-35c.c: Likewise. * gcc.target/i386/preserve-none-35d.c: Likewise. * gcc.target/i386/preserve-none-35e.c: Likewise. * gcc.target/i386/preserve-none-35f.c: Likewise. * gcc.target/i386/preserve-none-35g.c: Likewise. * gcc.target/i386/preserve-none-36a.c: Likewise. * gcc.target/i386/preserve-none-36b.c: Likewise. * gcc.target/i386/preserve-none-36c.c: Likewise. * gcc.target/i386/preserve-none-36d.c: Likewise. * gcc.target/i386/preserve-none-36e.c: Likewise. * gcc.target/i386/preserve-none-36f.c: Likewise. * gcc.target/i386/preserve-none-36g.c: Likewise. Signed-off-by: H.J. Lu <[email protected]> --- gcc/config/i386/i386.cc | 44 ++++++---- .../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 ++++ .../gcc.target/i386/preserve-none-35a.c | 55 ++++++++++++ .../gcc.target/i386/preserve-none-35b.c | 39 +++++++++ .../gcc.target/i386/preserve-none-35c.c | 34 ++++++++ .../gcc.target/i386/preserve-none-35d.c | 81 +++++++++++++++++ .../gcc.target/i386/preserve-none-35e.c | 34 ++++++++ .../gcc.target/i386/preserve-none-35f.c | 45 ++++++++++ .../gcc.target/i386/preserve-none-35g.c | 86 +++++++++++++++++++ .../gcc.target/i386/preserve-none-36a.c | 33 +++++++ .../gcc.target/i386/preserve-none-36b.c | 22 +++++ .../gcc.target/i386/preserve-none-36c.c | 18 ++++ .../gcc.target/i386/preserve-none-36d.c | 31 +++++++ .../gcc.target/i386/preserve-none-36e.c | 18 ++++ .../gcc.target/i386/preserve-none-36f.c | 36 ++++++++ .../gcc.target/i386/preserve-none-36g.c | 31 +++++++ 23 files changed, 808 insertions(+), 15 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 create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-35a.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-35b.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-35c.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-35d.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-35e.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-35f.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-35g.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-36a.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-36b.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-36c.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-36d.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-36e.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-36f.c create mode 100644 gcc/testsuite/gcc.target/i386/preserve-none-36g.c diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 1b8c03fecb9..7937f0c7eac 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 @@ -3622,10 +3638,8 @@ ix86_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg) if (TARGET_64BIT) { - enum calling_abi call_abi = cum ? cum->call_abi : ix86_abi; - /* See Windows x64 Software Convention. */ - if (call_abi == MS_ABI) + if (x86_64_cumulative_ms_abi_p (cum)) { HOST_WIDE_INT msize = GET_MODE_SIZE (arg.mode); @@ -4796,7 +4810,7 @@ ix86_setup_incoming_varargs (cumulative_args_t cum_v, && stdarg_p (fntype)) ix86_function_arg_advance (pack_cumulative_args (&next_cum), arg); - if (cum->call_abi == MS_ABI) + if (x86_64_cumulative_ms_abi_p (cum)) setup_incoming_varargs_ms_64 (&next_cum); else setup_incoming_varargs_64 (&next_cum); 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" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-35a.c b/gcc/testsuite/gcc.target/i386/preserve-none-35a.c new file mode 100644 index 00000000000..0bba3bfffef --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-35a.c @@ -0,0 +1,55 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** subq \$88, %rsp +** .cfi_def_cfa_offset 96 +** leaq 96\(%rsp\), %rax +** movq %r13, 40\(%rsp\) +** movq %rax, 8\(%rsp\) +** leaq 32\(%rsp\), %rax +** movq %rax, 16\(%rsp\) +** xorl %eax, %eax +** movq %r14, 48\(%rsp\) +** movq %r15, 56\(%rsp\) +** movq %rdi, 64\(%rsp\) +** movq %rsi, 72\(%rsp\) +** movl \$8, \(%rsp\) +** call continuation +** addq \$88, %rsp +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**... +*/ + +#include <stdarg.h> + +#ifndef CALLEE_ATTRIBUTE +#define CALLEE_ATTRIBUTE __attribute__ ((preserve_none, sysv_abi)) +#endif + +#ifndef CALLER_ATTRIBUTE +#define CALLER_ATTRIBUTE __attribute__ ((preserve_none, sysv_abi)) +#endif + +extern void continuation (int, ...) CALLEE_ATTRIBUTE; + +CALLER_ATTRIBUTE +void +entry (int i, ...) +{ + va_list argp; + va_start (argp, i); + int arg1 = va_arg (argp, int); + int arg2 = va_arg (argp, int); + int arg3 = va_arg (argp, int); + int arg4 = va_arg (argp, int); + int arg5 = va_arg (argp, int); + continuation (i, arg1, arg2, arg3, arg4, arg5); +} diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-35b.c b/gcc/testsuite/gcc.target/i386/preserve-none-35b.c new file mode 100644 index 00000000000..6d473e2e66b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-35b.c @@ -0,0 +1,39 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** subq \$88, %rsp +** .cfi_def_cfa_offset 96 +** movl %edi, %r12d +** movl %ecx, %r15d +** movl %r8d, %edi +** leaq 96\(%rsp\), %rax +** movq %rsi, 40\(%rsp\) +** movl %edx, %r14d +** movl %r9d, %esi +** movq %rax, 8\(%rsp\) +** movl 40\(%rsp\), %r13d +** leaq 32\(%rsp\), %rax +** movq %rax, 16\(%rsp\) +** xorl %eax, %eax +** movq %rdx, 48\(%rsp\) +** movq %rcx, 56\(%rsp\) +** movq %r8, 64\(%rsp\) +** movq %r9, 72\(%rsp\) +** movl \$8, \(%rsp\) +** call continuation +** addq \$88, %rsp +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**... +*/ + +#define CALLER_ATTRIBUTE __attribute__ ((no_callee_saved_registers, sysv_abi)) + +#include "preserve-none-35a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-35c.c b/gcc/testsuite/gcc.target/i386/preserve-none-35c.c new file mode 100644 index 00000000000..d05e68f0f17 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-35c.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** subq \$88, %rsp +** .cfi_def_cfa_offset 96 +** leaq 96\(%rsp\), %rax +** movq %rsi, 40\(%rsp\) +** movq %rax, 8\(%rsp\) +** leaq 32\(%rsp\), %rax +** movq %rax, 16\(%rsp\) +** xorl %eax, %eax +** movq %rdx, 48\(%rsp\) +** movq %rcx, 56\(%rsp\) +** movq %r8, 64\(%rsp\) +** movq %r9, 72\(%rsp\) +** movl \$8, \(%rsp\) +** call continuation +** addq \$88, %rsp +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**... +*/ + +#define CALLEE_ATTRIBUTE __attribute__ ((sysv_abi)) +#define CALLER_ATTRIBUTE __attribute__ ((sysv_abi)) + +#include "preserve-none-35a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-35d.c b/gcc/testsuite/gcc.target/i386/preserve-none-35d.c new file mode 100644 index 00000000000..6fc1ebfceaf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-35d.c @@ -0,0 +1,81 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB0: +** .cfi_startproc +** subq \$88, %rsp +** .cfi_def_cfa_offset 96 +** leaq 104\(%rsp\), %rax +** movq %rdx, 104\(%rsp\) +** movq %r8, 112\(%rsp\) +** movq %r9, 120\(%rsp\) +** movq \$0, 56\(%rsp\) +** movq \$0, 64\(%rsp\) +** movq %rax, 48\(%rsp\) +** cmpl \$47, %eax +** ja .L2 +** leal 8\(%rax\), %edx +** movl \(%eax\), %r10d +** cmpl \$47, %edx +** ja .L18 +** leal 16\(%rax\), %r9d +** movl \(%edx\), %r8d +** cmpl \$47, %r9d +** ja .L19 +** leal 24\(%rax\), %edx +** movl \(%r9d\), %r9d +** cmpl \$47, %edx +** ja .L20 +** addl \$32, %eax +** movl \(%edx\), %r11d +** cmpl \$47, %eax +** movl %eax, %edx +** movl \$0, %eax +** cmovbe %rdx, %rax +**.L9: +** movl \(%rax\), %eax +** movl %r11d, 32\(%rsp\) +** movl %r10d, %edx +** movl %eax, 40\(%rsp\) +** call continuation +** addq \$88, %rsp +** .cfi_remember_state +** .cfi_def_cfa_offset 8 +** ret +** .p2align 4,,10 +** .p2align 3 +**.L2: +** .cfi_restore_state +** movl 0, %r10d +** movl 8, %r8d +** movl \$16, %eax +**.L5: +** movl \(%rax\), %r9d +** leaq 8\(%rax\), %rdx +**.L7: +** movl \(%rdx\), %r11d +** leaq 8\(%rdx\), %rax +** jmp .L9 +**.L18: +** movl 0, %r8d +** movl \$8, %eax +** jmp .L5 +**.L20: +** xorl %edx, %edx +** jmp .L7 +**.L19: +** xorl %eax, %eax +** jmp .L5 +** .cfi_endproc +**.LFE0: +**... +*/ + +#define CALLEE_ATTRIBUTE __attribute__ ((ms_abi)) +#define CALLER_ATTRIBUTE __attribute__ ((ms_abi)) + +#include "preserve-none-35a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-35e.c b/gcc/testsuite/gcc.target/i386/preserve-none-35e.c new file mode 100644 index 00000000000..d1f0209b854 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-35e.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** subq \$88, %rsp +** .cfi_def_cfa_offset 96 +** leaq 96\(%rsp\), %rax +** movq %r13, 40\(%rsp\) +** movq %rax, 8\(%rsp\) +** leaq 32\(%rsp\), %rax +** movq %rax, 16\(%rsp\) +** xorl %eax, %eax +** movq %r14, 48\(%rsp\) +** movq %r15, 56\(%rsp\) +** movq %rdi, 64\(%rsp\) +** movq %rsi, 72\(%rsp\) +** movl \$8, \(%rsp\) +** call continuation +** addq \$88, %rsp +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**... +*/ + +#define CALLEE_ATTRIBUTE __attribute__ ((preserve_none, ms_abi)) +#define CALLER_ATTRIBUTE __attribute__ ((preserve_none, ms_abi)) + +#include "preserve-none-35a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-35f.c b/gcc/testsuite/gcc.target/i386/preserve-none-35f.c new file mode 100644 index 00000000000..2af54293e3a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-35f.c @@ -0,0 +1,45 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB0: +** .cfi_startproc +** subq \$88, %rsp +** .cfi_def_cfa_offset 96 +** movl %r12d, %ecx +** leaq 96\(%rsp\), %rax +** movq %rsi, 72\(%rsp\) +** movq %rax, 8\(%rsp\) +** leaq 32\(%rsp\), %rax +** movq %rax, 16\(%rsp\) +** movq %r13, 40\(%rsp\) +** movq %r14, 48\(%rsp\) +** movq %r15, 56\(%rsp\) +** movq %rdi, 64\(%rsp\) +** movl \$8, \(%rsp\) +** pushq %rsi +** .cfi_def_cfa_offset 104 +** movl 72\(%rsp\), %eax +** pushq %rax +** .cfi_def_cfa_offset 112 +** subq \$32, %rsp +** .cfi_def_cfa_offset 144 +** movl 104\(%rsp\), %r9d +** movl 96\(%rsp\), %r8d +** movl 88\(%rsp\), %edx +** call continuation +** addq \$136, %rsp +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**.LFE0: +**... +*/ + +#define CALLEE_ATTRIBUTE __attribute__ ((no_callee_saved_registers, ms_abi)) +#define CALLER_ATTRIBUTE __attribute__ ((preserve_none, ms_abi)) + +#include "preserve-none-35a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-35g.c b/gcc/testsuite/gcc.target/i386/preserve-none-35g.c new file mode 100644 index 00000000000..15940900b0b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-35g.c @@ -0,0 +1,86 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB0: +** .cfi_startproc +** subq \$40, %rsp +** .cfi_def_cfa_offset 48 +** movl %ecx, %r12d +** leaq 56\(%rsp\), %rax +** movq %rdx, 56\(%rsp\) +** movq %r8, 64\(%rsp\) +** movq %r9, 72\(%rsp\) +** movq \$0, 8\(%rsp\) +** movq \$0, 16\(%rsp\) +** movq %rax, \(%rsp\) +** cmpl \$47, %eax +** ja .L2 +** leal 8\(%rax\), %edx +** movl \(%eax\), %r13d +** cmpl \$47, %edx +** ja .L18 +** leal 16\(%rax\), %ecx +** movl \(%edx\), %r14d +** cmpl \$47, %ecx +** ja .L19 +** leal 24\(%rax\), %edx +** movl \(%ecx\), %r15d +** cmpl \$47, %edx +** ja .L20 +** addl \$32, %eax +** movl \(%edx\), %edi +** cmpl \$47, %eax +** movl %eax, %edx +** movl \$0, %eax +** cmovbe %rdx, %rax +** movl \(%rax\), %esi +** xorl %eax, %eax +** call continuation +** addq \$40, %rsp +** .cfi_remember_state +** .cfi_def_cfa_offset 8 +** ret +** .p2align 4,,10 +** .p2align 3 +**.L2: +** .cfi_restore_state +** movl 0, %r13d +** movl 8, %r14d +** movl \$16, %eax +**.L5: +** movl \(%rax\), %r15d +** leaq 8\(%rax\), %rdx +**.L7: +** movl 8\(%rdx\), %esi +** movl \(%rdx\), %edi +** leaq 8\(%rdx\), %rax +** xorl %eax, %eax +** call continuation +** addq \$40, %rsp +** .cfi_remember_state +** .cfi_def_cfa_offset 8 +** ret +**.L18: +** .cfi_restore_state +** movl 0, %r14d +** movl \$8, %eax +** jmp .L5 +**.L20: +** xorl %edx, %edx +** jmp .L7 +**.L19: +** xorl %eax, %eax +** jmp .L5 +** .cfi_endproc +**.LFE0: +**... +*/ + +#define CALLEE_ATTRIBUTE __attribute__ ((preserve_none, ms_abi)) +#define CALLER_ATTRIBUTE __attribute__ ((no_callee_saved_registers, ms_abi)) + +#include "preserve-none-35a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-36a.c b/gcc/testsuite/gcc.target/i386/preserve-none-36a.c new file mode 100644 index 00000000000..bf5fe5196f8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-36a.c @@ -0,0 +1,33 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -march=x86-64 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** jmp continuation +** .cfi_endproc +**... +*/ + +#ifndef CALLEE_ATTRIBUTE +#define CALLEE_ATTRIBUTE __attribute__ ((preserve_none, sysv_abi)) +#endif + +#ifndef CALLER_ATTRIBUTE +#define CALLER_ATTRIBUTE __attribute__ ((preserve_none, sysv_abi)) +#endif + +typedef float v4sf __attribute__((vector_size(16))); + +extern void continuation (long, long, long, long, long, v4sf) + CALLEE_ATTRIBUTE; + +CALLER_ATTRIBUTE +void +entry (long arg1, long arg2, long arg3, long arg4, long arg5, v4sf arg6) +{ + continuation (arg1, arg2, arg3, arg4, arg5, arg6); +} diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-36b.c b/gcc/testsuite/gcc.target/i386/preserve-none-36b.c new file mode 100644 index 00000000000..9a110b309ba --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-36b.c @@ -0,0 +1,22 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -march=x86-64 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** movq %rdi, %r12 +** movq %rsi, %r13 +** movq %rdx, %r14 +** movq %rcx, %r15 +** movq %r8, %rdi +** jmp continuation +** .cfi_endproc +**... +*/ + +#define CALLER_ATTRIBUTE __attribute__ ((no_callee_saved_registers, sysv_abi)) + +#include "preserve-none-36a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-36c.c b/gcc/testsuite/gcc.target/i386/preserve-none-36c.c new file mode 100644 index 00000000000..200aeb9b579 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-36c.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -march=x86-64 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** jmp continuation +** .cfi_endproc +**... +*/ + +#define CALLEE_ATTRIBUTE __attribute__ ((sysv_abi)) +#define CALLER_ATTRIBUTE __attribute__ ((sysv_abi)) + +#include "preserve-none-36a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-36d.c b/gcc/testsuite/gcc.target/i386/preserve-none-36d.c new file mode 100644 index 00000000000..7d82464c925 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-36d.c @@ -0,0 +1,31 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -march=x86-64 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** subq \$72, %rsp +** .cfi_def_cfa_offset 80 +** movq 120\(%rsp\), %rax +** movaps \(%rax\), %xmm0 +** leaq 48\(%rsp\), %rax +** movq %rax, 40\(%rsp\) +** movq 112\(%rsp\), %rax +** movaps %xmm0, 48\(%rsp\) +** movq %rax, 32\(%rsp\) +** call continuation +** addq \$72, %rsp +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**.LFE0: +**... +*/ + +#define CALLEE_ATTRIBUTE __attribute__ ((ms_abi)) +#define CALLER_ATTRIBUTE __attribute__ ((ms_abi)) + +#include "preserve-none-36a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-36e.c b/gcc/testsuite/gcc.target/i386/preserve-none-36e.c new file mode 100644 index 00000000000..87cb8e763bd --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-36e.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -march=x86-64 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB[0-9]+: +** .cfi_startproc +** jmp continuation +** .cfi_endproc +**... +*/ + +#define CALLEE_ATTRIBUTE __attribute__ ((preserve_none, ms_abi)) +#define CALLER_ATTRIBUTE __attribute__ ((preserve_none, ms_abi)) + +#include "preserve-none-36a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-36f.c b/gcc/testsuite/gcc.target/i386/preserve-none-36f.c new file mode 100644 index 00000000000..2a6fccfdc23 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-36f.c @@ -0,0 +1,36 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -march=x86-64 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB0: +** .cfi_startproc +** subq \$24, %rsp +** .cfi_def_cfa_offset 32 +** movq %r14, %r8 +** movq %r15, %r9 +** movq %r13, %rdx +** movq %rsp, %rax +** movaps %xmm0, \(%rsp\) +** movq %r12, %rcx +** pushq %rax +** .cfi_def_cfa_offset 40 +** pushq %rdi +** .cfi_def_cfa_offset 48 +** subq \$32, %rsp +** .cfi_def_cfa_offset 80 +** call continuation +** addq \$72, %rsp +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**.LFE0: +**... +*/ + +#define CALLEE_ATTRIBUTE __attribute__ ((no_callee_saved_registers, ms_abi)) +#define CALLER_ATTRIBUTE __attribute__ ((preserve_none, ms_abi)) + +#include "preserve-none-36a.c" diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-36g.c b/gcc/testsuite/gcc.target/i386/preserve-none-36g.c new file mode 100644 index 00000000000..30f6f27ad5c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/preserve-none-36g.c @@ -0,0 +1,31 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -march=x86-64 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**entry: +**.LFB0: +** .cfi_startproc +** subq \$8, %rsp +** .cfi_def_cfa_offset 16 +** movq %rcx, %r12 +** movq %rdx, %r13 +** movq %r9, %r15 +** movq 56\(%rsp\), %rax +** movq 48\(%rsp\), %rdi +** movq %r8, %r14 +** movaps \(%rax\), %xmm0 +** call continuation +** addq \$8, %rsp +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**.LFE0: +**... +*/ + +#define CALLEE_ATTRIBUTE __attribute__ ((preserve_none, ms_abi)) +#define CALLER_ATTRIBUTE __attribute__ ((no_callee_saved_registers, ms_abi)) + +#include "preserve-none-36a.c" -- 2.55.0
