This patch extends the generation of exception handling information to cover all asm statements, when -fnon-call-exceptions is given. The previous patch only enabled this for volatile asms.
The previously added test cases are adjusted to cover this change. gcc/ 2020-03-11 Jan W. Jagersma <jwjager...@gmail.com> PR inline-asm/93981 * tree-eh.c (tree_could_trap_p): Return true for case ASM_EXPR. (stmt_could_throw_p): Likewise, for GIMPLE_ASM. * rtlanal.c (may_trap_p_1): Likewise, for ASM_OPERANDS. * doc/extend.texi: Document this change in the appropriate subsection. gcc/testsuite/ 2020-03-11 Jan W. Jagersma <jwjager...@gmail.com> PR inline-asm/93981 * g++.dg/eh/pr93981.C: Cover non-volatile throwing asms. * g++.target/i386/pr93981.C: Likewise. --- gcc/doc/extend.texi | 10 +++---- gcc/rtlanal.c | 4 +-- gcc/testsuite/g++.dg/eh/pr93981.C | 22 ++++++++++++--- gcc/testsuite/g++.target/i386/pr93981.C | 36 ++++++++++++++++++++++--- gcc/tree-eh.c | 4 +-- 5 files changed, 60 insertions(+), 16 deletions(-) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index b51e34c617a..43929d9b129 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -9454,6 +9454,11 @@ printf("%d\n", dst); This code copies @code{src} to @code{dst} and add 1 to @code{dst}. +When non-call exceptions (@option{-fnon-call-exceptions}) are enabled, an +@code{asm} statement is also allowed to throw exceptions. If it does, then its +register output operands are assumed to be clobbered and will not be used. +Memory operands, however, are always considered valid. + @anchor{Volatile} @subsubsection Volatile @cindex volatile @code{asm} @@ -9577,11 +9582,6 @@ errors during compilation if your @code{asm} code defines symbols or labels. Using @samp{%=} (@pxref{AssemblerTemplate}) may help resolve this problem. -When non-call exceptions (@option{-fnon-call-exceptions}) are enabled, a -@code{volatile asm} statement is also allowed to throw exceptions. If it does, -then its register output operands are assumed to be clobbered and will not be -used. Memory operands, however, are always considered valid. - @anchor{AssemblerTemplate} @subsubsection Assembler Template @cindex @code{asm} assembler template diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index c7ab86e228b..e7eb2dad11b 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -2831,13 +2831,11 @@ may_trap_p_1 (const_rtx x, unsigned flags) return targetm.unspec_may_trap_p (x, flags); case UNSPEC_VOLATILE: + case ASM_OPERANDS: case ASM_INPUT: case TRAP_IF: return 1; - case ASM_OPERANDS: - return MEM_VOLATILE_P (x); - /* Memory ref can trap unless it's a static var or a stack slot. */ case MEM: /* Recognize specific pattern of stack checking probes. */ diff --git a/gcc/testsuite/g++.dg/eh/pr93981.C b/gcc/testsuite/g++.dg/eh/pr93981.C index a9adb5c069e..2e0d1cb881c 100644 --- a/gcc/testsuite/g++.dg/eh/pr93981.C +++ b/gcc/testsuite/g++.dg/eh/pr93981.C @@ -3,7 +3,7 @@ // { dg-options "-fnon-call-exceptions" } void -f () +foo () { try { @@ -11,8 +11,24 @@ f () } catch (...) { - asm ("#catch"); + asm ("#catch-v"); } } -// { dg-final { scan-assembler "#catch" } } +int +bar () +{ + int i; + try + { + asm ("#try" : "=rm" (i)); + } + catch (...) + { + asm ("#catch-nv"); + } + return i; +} + +// { dg-final { scan-assembler "#catch-v" } } +// { dg-final { scan-assembler "#catch-nv" } } diff --git a/gcc/testsuite/g++.target/i386/pr93981.C b/gcc/testsuite/g++.target/i386/pr93981.C index 7a3117901f9..e4b5d7cd90f 100644 --- a/gcc/testsuite/g++.target/i386/pr93981.C +++ b/gcc/testsuite/g++.target/i386/pr93981.C @@ -15,7 +15,7 @@ sigill (int) } int -test_mem () +test_mem_v () { int i = 2; try @@ -30,7 +30,7 @@ test_mem () } int -test_reg () +test_reg_v () { int i = 8; try @@ -44,6 +44,36 @@ test_reg () return i; } +int +test_mem_nv () +{ + int i = 32; + try + { + asm ("mov%z0 $16, %0; ud2" : "=m" (i)); + } + catch (const illegal_opcode&) + { + if (i == 16) return 0; + } + return i; +} + +int +test_reg_nv () +{ + int i = 128; + try + { + asm ("mov%z0 $64, %0; ud2" : "=r" (i)); + } + catch (const illegal_opcode&) + { + if (i == 128) return 0; + } + return i; +} + int main () { @@ -51,5 +81,5 @@ main () sa.sa_handler = sigill; sa.sa_flags = SA_NODEFER; sigaction (SIGILL, &sa, 0); - return test_mem () | test_reg (); + return test_mem_v () | test_reg_v () | test_mem_nv () | test_reg_nv (); } diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 58b16aa763a..b2e17099320 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -2760,7 +2760,7 @@ tree_could_trap_p (tree expr) return !TREE_THIS_NOTRAP (expr); case ASM_EXPR: - return TREE_THIS_VOLATILE (expr); + return true; case CALL_EXPR: t = get_callee_fndecl (expr); @@ -2964,7 +2964,7 @@ stmt_could_throw_p (function *fun, gimple *stmt) case GIMPLE_ASM: if (fun && !fun->can_throw_non_call_exceptions) return false; - return gimple_asm_volatile_p (as_a <gasm *> (stmt)); + return true; default: return false; -- 2.25.1