Clobbering the stack pointer in asm statment has been deprecated. Adding the stack pointer register to the clobber list has traditionally had some undocumented and somewhat obscure side-effects, including ICE. Issue a warning and ignore the clobbered stack pointer in asm statment.
gcc/ PR target/97032 * cfgexpand.c (asm_clobber_reg_kind): New enum. (asm_clobber_reg_is_valid): Renamed to ... (get_asm_clobber_reg_kind): This. Ignore the stack pointer. (expand_asm_stmt): Replace asm_clobber_reg_is_valid with get_asm_clobber_reg_kind. Skip ignored clobbered register. gcc/testsuite/ PR target/97032 * gcc.target/i386/pr97032.c: New test. --- gcc/cfgexpand.c | 45 ++++++++++++++++++------- gcc/testsuite/gcc.target/i386/pr97032.c | 23 +++++++++++++ 2 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr97032.c diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index b334ea03c25..433e7889138 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -2832,14 +2832,21 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs) return false; } +enum asm_clobber_reg_kind +{ + asm_clobber_reg_valid, + asm_clobber_reg_invalid, + asm_clobber_reg_ignored +}; + /* Check that the given REGNO spanning NREGS is a valid asm clobber operand. Some HW registers cannot be saved/restored, hence they should not be clobbered by asm statements. */ -static bool -asm_clobber_reg_is_valid (int regno, int nregs, const char *regname) +static asm_clobber_reg_kind +get_asm_clobber_reg_kind (int regno, int nregs, const char *regname) { - bool is_valid = true; + asm_clobber_reg_kind kind = asm_clobber_reg_valid; HARD_REG_SET regset; CLEAR_HARD_REG_SET (regset); @@ -2852,7 +2859,7 @@ asm_clobber_reg_is_valid (int regno, int nregs, const char *regname) { /* ??? Diagnose during gimplification? */ error ("PIC register clobbered by %qs in %<asm%>", regname); - is_valid = false; + kind = asm_clobber_reg_invalid; } else if (!in_hard_reg_set_p (accessible_reg_set, reg_raw_mode[regno], regno)) @@ -2860,7 +2867,7 @@ asm_clobber_reg_is_valid (int regno, int nregs, const char *regname) /* ??? Diagnose during gimplification? */ error ("the register %qs cannot be clobbered in %<asm%>" " for the current target", regname); - is_valid = false; + kind = asm_clobber_reg_invalid; } /* Clobbering the stack pointer register is deprecated. GCC expects @@ -2868,13 +2875,18 @@ asm_clobber_reg_is_valid (int regno, int nregs, const char *regname) as it was before, so no asm can validly clobber the stack pointer in the usual sense. Adding the stack pointer to the clobber list has traditionally had some undocumented and somewhat obscure side-effects. */ - if (overlaps_hard_reg_set_p (regset, Pmode, STACK_POINTER_REGNUM) - && warning (OPT_Wdeprecated, "listing the stack pointer register" - " %qs in a clobber list is deprecated", regname)) - inform (input_location, "the value of the stack pointer after an %<asm%>" - " statement must be the same as it was before the statement"); + if (overlaps_hard_reg_set_p (regset, Pmode, STACK_POINTER_REGNUM)) + { + kind = asm_clobber_reg_ignored; + if (warning (OPT_Wdeprecated, "listing the stack pointer register" + " %qs in a clobber list is deprecated and ignored", + regname)) + inform (input_location, "the value of the stack pointer after" + " an %<asm%> statement must be the same as it was" + " before the statement"); + } - return is_valid; + return kind; } /* Generate RTL for an asm statement with arguments. @@ -3009,8 +3021,15 @@ expand_asm_stmt (gasm *stmt) else for (int reg = j; reg < j + nregs; reg++) { - if (!asm_clobber_reg_is_valid (reg, nregs, regname)) - return; + switch (get_asm_clobber_reg_kind (reg, nregs, regname)) + { + case asm_clobber_reg_valid: + break; + case asm_clobber_reg_invalid: + return; + case asm_clobber_reg_ignored: + continue; + } SET_HARD_REG_BIT (clobbered_regs, reg); rtx x = gen_rtx_REG (reg_raw_mode[reg], reg); diff --git a/gcc/testsuite/gcc.target/i386/pr97032.c b/gcc/testsuite/gcc.target/i386/pr97032.c new file mode 100644 index 00000000000..7cbbe9bc22a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr97032.c @@ -0,0 +1,23 @@ +/* { dg-do compile { target { ia32 && fstack_protector } } } */ +/* { dg-options "-O2 -mincoming-stack-boundary=2 -fstack-protector-all" } */ + +#include <stdarg.h> + +extern int *__errno_location (void); + +long +sys_socketcall (int op, ...) +{ + long int res; + va_list ap; + va_start (ap, op); + asm volatile ("push %%ebx; movl %2, %%ebx; int $0x80; pop %%ebx" + /* { dg-warning "listing the stack pointer register" "" { target *-*-* } .-1 } */ + : "=a" (res) : "0" (102), "ri" (16), "c" (ap) : "memory", "esp"); + if (__builtin_expect (res > 4294963200UL, 0)) + *__errno_location () = -res; + va_end (ap); + return res; +} + +/* { dg-final { scan-assembler "call\[ \t\]*_?__errno_location" } } */ -- 2.26.2