xtensa: libgcc: fix PR target/95571
Rewrite uw_install_context without function calls to avoid register spilling in _Unwind_RaiseException during return context installation. 2020-06-08 Max Filippov <jcmvbkbc@gmail.com> gcc/testsuite/ * g++.target/xtensa/pr95571.C: New test. * g++.target/xtensa/xtensa.exp: New testsuite. libgcc/ * config/xtensa/unwind-dw2-xtensa.c (uw_install_context): Merge with uw_install_context_1.
This commit is contained in:
parent
df2c0060e5
commit
1d9921cbdc
|
@ -0,0 +1,43 @@
|
|||
/* { dg-do run } */
|
||||
|
||||
extern "C" void abort(void);
|
||||
extern "C" void __xtensa_libgcc_window_spill(void);
|
||||
|
||||
static int call;
|
||||
static int cnt;
|
||||
|
||||
extern "C" void *memcpy(void *dst, const void *src, unsigned int sz)
|
||||
{
|
||||
char *a = (char *)dst;
|
||||
const char *b = (const char *)src;
|
||||
|
||||
if (call++ == cnt)
|
||||
__xtensa_libgcc_window_spill();
|
||||
|
||||
while (sz--)
|
||||
*a++ = *b++;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 100; ++i)
|
||||
{
|
||||
call = 0;
|
||||
cnt = i;
|
||||
|
||||
try
|
||||
{
|
||||
throw 1;
|
||||
}
|
||||
catch (int v)
|
||||
{
|
||||
if (v != 1)
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
# Specific regression driver for Xtensa.
|
||||
# Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GCC.
|
||||
#
|
||||
# GCC is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# GCC 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/>. */
|
||||
|
||||
# GCC testsuite that uses the `dg.exp' driver.
|
||||
|
||||
# Exit immediately if this isn't an Xtensa target.
|
||||
if {![istarget xtensa*-*-*] } then {
|
||||
return
|
||||
}
|
||||
|
||||
# Load support procs.
|
||||
load_lib g++-dg.exp
|
||||
|
||||
global DEFAULT_CXXFLAGS
|
||||
if ![info exists DEFAULT_CXXFLAGS] then {
|
||||
set DEFAULT_CXXFLAGS " -pedantic-errors"
|
||||
}
|
||||
|
||||
# Initialize `dg'.
|
||||
dg-init
|
||||
|
||||
# Main loop.
|
||||
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] \
|
||||
"" $DEFAULT_CXXFLAGS
|
||||
|
||||
# All done.
|
||||
dg-finish
|
|
@ -481,37 +481,35 @@ uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa,
|
|||
|
||||
/* Install TARGET into CURRENT so that we can return to it. This is a
|
||||
macro because __builtin_eh_return must be invoked in the context of
|
||||
our caller. */
|
||||
our caller, and also because spilling registers of the caller before
|
||||
the context installation may result in reload of wrong register values
|
||||
after the context installation due to the change of the stack pointer
|
||||
in the base save area. This spilling may be caused by an interrupt
|
||||
handler on baremetal host. */
|
||||
|
||||
#define uw_install_context(CURRENT, TARGET, FRAMES) \
|
||||
#define uw_install_context(CURRENT, TARGET, FRAMES) \
|
||||
do \
|
||||
{ \
|
||||
long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
|
||||
void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
|
||||
__builtin_eh_return (offset, handler); \
|
||||
long i; \
|
||||
\
|
||||
/* The eh_return insn assumes a window size of 8, so don't bother \
|
||||
copying the save areas for registers a8-a15 since they won't be \
|
||||
reloaded. */ \
|
||||
for (i = 0; i < 2; ++i) \
|
||||
{ \
|
||||
_Unwind_Word *c = (CURRENT)->reg[i]; \
|
||||
_Unwind_Word *t = (TARGET)->reg[i]; \
|
||||
int j; \
|
||||
\
|
||||
if (t && c && t != c) \
|
||||
for (j = 0; j < 4; ++j) \
|
||||
*c++ = *t++; \
|
||||
} \
|
||||
__builtin_eh_return (0, handler); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
static long
|
||||
uw_install_context_1 (struct _Unwind_Context *current,
|
||||
struct _Unwind_Context *target)
|
||||
{
|
||||
long i;
|
||||
|
||||
/* The eh_return insn assumes a window size of 8, so don't bother copying
|
||||
the save areas for registers a8-a15 since they won't be reloaded. */
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
void *c = current->reg[i];
|
||||
void *t = target->reg[i];
|
||||
|
||||
if (t && c && t != c)
|
||||
memcpy (c, t, 4 * sizeof (_Unwind_Word));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline _Unwind_Ptr
|
||||
uw_identify_context (struct _Unwind_Context *context)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue