- backport from 11.3.1-4.4: s390x: add support for register arguments preserving (#2168204)
- backport from 11.3.1-4.3: compile the cross binaries as PIE/-z now (#2155452) - backport from 11.3.1-4.2: ship libitm.spec in cross-gcc (#2154462) - backport from 11.3.1-4.1: add cross compiler functionality for non-production uses (#2149650) - backport from 11.3.1-4: update from releases/gcc-11-branch (#2117632) - backport from 11.3.1-4: fix the detection of Sapphire Rapids in host_detect_local_cpu - backport from 11.3.1-4: fix -Wmismatched-dealloc documentation (#2116635)epel9
parent
28d73354d1
commit
a182f14beb
@ -0,0 +1,79 @@
|
|||||||
|
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
|
||||||
|
index 3419483c532..a2a6b1c98be 100644
|
||||||
|
--- a/gcc/doc/invoke.texi
|
||||||
|
+++ b/gcc/doc/invoke.texi
|
||||||
|
@@ -255,7 +255,7 @@ in the following sections.
|
||||||
|
-Wno-inherited-variadic-ctor -Wno-init-list-lifetime @gol
|
||||||
|
-Winvalid-imported-macros @gol
|
||||||
|
-Wno-invalid-offsetof -Wno-literal-suffix @gol
|
||||||
|
--Wno-mismatched-new-delete -Wmismatched-tags @gol
|
||||||
|
+-Wmismatched-new-delete -Wmismatched-tags @gol
|
||||||
|
-Wmultiple-inheritance -Wnamespaces -Wnarrowing @gol
|
||||||
|
-Wnoexcept -Wnoexcept-type -Wnon-virtual-dtor @gol
|
||||||
|
-Wpessimizing-move -Wno-placement-new -Wplacement-new=@var{n} @gol
|
||||||
|
@@ -3966,7 +3966,7 @@ The warning is inactive inside a system header file, such as the STL, so
|
||||||
|
one can still use the STL. One may also instantiate or specialize
|
||||||
|
templates.
|
||||||
|
|
||||||
|
-@item -Wno-mismatched-new-delete @r{(C++ and Objective-C++ only)}
|
||||||
|
+@item -Wmismatched-new-delete @r{(C++ and Objective-C++ only)}
|
||||||
|
@opindex Wmismatched-new-delete
|
||||||
|
@opindex Wno-mismatched-new-delete
|
||||||
|
Warn for mismatches between calls to @code{operator new} or @code{operator
|
||||||
|
@@ -3998,7 +3998,7 @@ The related option @option{-Wmismatched-dealloc} diagnoses mismatches
|
||||||
|
involving allocation and deallocation functions other than @code{operator
|
||||||
|
new} and @code{operator delete}.
|
||||||
|
|
||||||
|
-@option{-Wmismatched-new-delete} is enabled by default.
|
||||||
|
+@option{-Wmismatched-new-delete} is included in @option{-Wall}.
|
||||||
|
|
||||||
|
@item -Wmismatched-tags @r{(C++ and Objective-C++ only)}
|
||||||
|
@opindex Wmismatched-tags
|
||||||
|
@@ -5543,6 +5543,8 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
|
||||||
|
-Wmemset-elt-size @gol
|
||||||
|
-Wmemset-transposed-args @gol
|
||||||
|
-Wmisleading-indentation @r{(only for C/C++)} @gol
|
||||||
|
+-Wmismatched-dealloc @gol
|
||||||
|
+-Wmismatched-new-delete @r{(only for C/C++)} @gol
|
||||||
|
-Wmissing-attributes @gol
|
||||||
|
-Wmissing-braces @r{(only for C/ObjC)} @gol
|
||||||
|
-Wmultistatement-macros @gol
|
||||||
|
@@ -6428,7 +6430,7 @@ Ignoring the warning can result in poorly optimized code.
|
||||||
|
disable the warning, but this is not recommended and should be done only
|
||||||
|
when non-existent profile data is justified.
|
||||||
|
|
||||||
|
-@item -Wno-mismatched-dealloc
|
||||||
|
+@item -Wmismatched-dealloc
|
||||||
|
@opindex Wmismatched-dealloc
|
||||||
|
@opindex Wno-mismatched-dealloc
|
||||||
|
|
||||||
|
@@ -6461,7 +6463,7 @@ void f (void)
|
||||||
|
In C++, the related option @option{-Wmismatched-new-delete} diagnoses
|
||||||
|
mismatches involving either @code{operator new} or @code{operator delete}.
|
||||||
|
|
||||||
|
-Option @option{-Wmismatched-dealloc} is enabled by default.
|
||||||
|
+Option @option{-Wmismatched-dealloc} is included in @option{-Wall}.
|
||||||
|
|
||||||
|
@item -Wmultistatement-macros
|
||||||
|
@opindex Wmultistatement-macros
|
||||||
|
@@ -7951,9 +7953,9 @@ Warnings controlled by the option can be disabled either by specifying
|
||||||
|
Disable @option{-Wframe-larger-than=} warnings. The option is equivalent
|
||||||
|
to @option{-Wframe-larger-than=}@samp{SIZE_MAX} or larger.
|
||||||
|
|
||||||
|
-@item -Wno-free-nonheap-object
|
||||||
|
-@opindex Wno-free-nonheap-object
|
||||||
|
+@item -Wfree-nonheap-object
|
||||||
|
@opindex Wfree-nonheap-object
|
||||||
|
+@opindex Wno-free-nonheap-object
|
||||||
|
Warn when attempting to deallocate an object that was either not allocated
|
||||||
|
on the heap, or by using a pointer that was not returned from a prior call
|
||||||
|
to the corresponding allocation function. For example, because the call
|
||||||
|
@@ -7970,7 +7972,7 @@ void f (char *p)
|
||||||
|
@}
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
-@option{-Wfree-nonheap-object} is enabled by default.
|
||||||
|
+@option{-Wfree-nonheap-object} is included in @option{-Wall}.
|
||||||
|
|
||||||
|
@item -Wstack-usage=@var{byte-size}
|
||||||
|
@opindex Wstack-usage
|
@ -0,0 +1,69 @@
|
|||||||
|
commit 63dd214dce603f4f99e2cb272255b6c2b4308c3d
|
||||||
|
Author: Cui,Lili <lili.cui@intel.com>
|
||||||
|
Date: Mon Nov 7 11:25:41 2022 +0800
|
||||||
|
|
||||||
|
Remove AVX512_VP2INTERSECT from PTA_SAPPHIRERAPIDS
|
||||||
|
|
||||||
|
gcc/ChangeLog:
|
||||||
|
|
||||||
|
* config/i386/driver-i386.cc (host_detect_local_cpu):
|
||||||
|
Move sapphirerapids out of AVX512_VP2INTERSECT.
|
||||||
|
* config/i386/i386.h: Remove AVX512_VP2INTERSECT from PTA_SAPPHIRERAPIDS
|
||||||
|
* doc/invoke.texi: Remove AVX512_VP2INTERSECT from SAPPHIRERAPIDS
|
||||||
|
|
||||||
|
(cherry picked from commit d644dfe36d9733c767af62d37250253ced6efd8c)
|
||||||
|
|
||||||
|
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
|
||||||
|
index f844a168ddb..90f84aba4ee 100644
|
||||||
|
--- a/gcc/config/i386/driver-i386.c
|
||||||
|
+++ b/gcc/config/i386/driver-i386.c
|
||||||
|
@@ -574,15 +574,12 @@ const char *host_detect_local_cpu (int argc, const char **argv)
|
||||||
|
/* This is unknown family 0x6 CPU. */
|
||||||
|
if (has_feature (FEATURE_AVX))
|
||||||
|
{
|
||||||
|
+ /* Assume Tiger Lake */
|
||||||
|
if (has_feature (FEATURE_AVX512VP2INTERSECT))
|
||||||
|
- {
|
||||||
|
- if (has_feature (FEATURE_TSXLDTRK))
|
||||||
|
- /* Assume Sapphire Rapids. */
|
||||||
|
- cpu = "sapphirerapids";
|
||||||
|
- else
|
||||||
|
- /* Assume Tiger Lake */
|
||||||
|
- cpu = "tigerlake";
|
||||||
|
- }
|
||||||
|
+ cpu = "tigerlake";
|
||||||
|
+ /* Assume Sapphire Rapids. */
|
||||||
|
+ else if (has_feature (FEATURE_TSXLDTRK))
|
||||||
|
+ cpu = "sapphirerapids";
|
||||||
|
/* Assume Cooper Lake */
|
||||||
|
else if (has_feature (FEATURE_AVX512BF16))
|
||||||
|
cpu = "cooperlake";
|
||||||
|
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
|
||||||
|
index ac0e5da623c..e03279bcf39 100644
|
||||||
|
--- a/gcc/config/i386/i386.h
|
||||||
|
+++ b/gcc/config/i386/i386.h
|
||||||
|
@@ -2562,7 +2562,7 @@ constexpr wide_int_bitmask PTA_ICELAKE_SERVER = PTA_ICELAKE_CLIENT
|
||||||
|
constexpr wide_int_bitmask PTA_TIGERLAKE = PTA_ICELAKE_CLIENT | PTA_MOVDIRI
|
||||||
|
| PTA_MOVDIR64B | PTA_CLWB | PTA_AVX512VP2INTERSECT | PTA_KL | PTA_WIDEKL;
|
||||||
|
constexpr wide_int_bitmask PTA_SAPPHIRERAPIDS = PTA_ICELAKE_SERVER | PTA_MOVDIRI
|
||||||
|
- | PTA_MOVDIR64B | PTA_AVX512VP2INTERSECT | PTA_ENQCMD | PTA_CLDEMOTE
|
||||||
|
+ | PTA_MOVDIR64B | PTA_ENQCMD | PTA_CLDEMOTE
|
||||||
|
| PTA_PTWRITE | PTA_WAITPKG | PTA_SERIALIZE | PTA_TSXLDTRK | PTA_AMX_TILE
|
||||||
|
| PTA_AMX_INT8 | PTA_AMX_BF16 | PTA_UINTR | PTA_AVXVNNI | PTA_AVX512BF16;
|
||||||
|
constexpr wide_int_bitmask PTA_KNL = PTA_BROADWELL | PTA_AVX512PF
|
||||||
|
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
|
||||||
|
index 3419483c532..6b3afb827a5 100644
|
||||||
|
--- a/gcc/doc/invoke.texi
|
||||||
|
+++ b/gcc/doc/invoke.texi
|
||||||
|
@@ -30236,9 +30236,9 @@ Intel sapphirerapids CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3,
|
||||||
|
SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE,
|
||||||
|
RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW,
|
||||||
|
AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ,
|
||||||
|
-AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2
|
||||||
|
+AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2,
|
||||||
|
VPCLMULQDQ, AVX512BITALG, RDPID, AVX512VPOPCNTDQ, PCONFIG, WBNOINVD, CLWB,
|
||||||
|
-MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG,
|
||||||
|
+MOVDIRI, MOVDIR64B, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG,
|
||||||
|
SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI and
|
||||||
|
AVX512BF16 instruction set support.
|
||||||
|
|
@ -1,33 +0,0 @@
|
|||||||
2022-04-21 Jakub Jelinek <jakub@redhat.com>
|
|
||||||
|
|
||||||
PR target/105331
|
|
||||||
* config/i386/i386.c (ix86_gimplify_va_arg): Mark va_arg_tmp
|
|
||||||
temporary TREE_ADDRESSABLE before trying to gimplify ADDR_EXPR
|
|
||||||
of it.
|
|
||||||
|
|
||||||
* gcc.dg/pr105331.c: New test.
|
|
||||||
|
|
||||||
--- gcc/config/i386/i386.c.jj 2022-04-12 09:20:07.566662842 +0200
|
|
||||||
+++ gcc/config/i386/i386.c 2022-04-21 12:03:32.201951522 +0200
|
|
||||||
@@ -4891,6 +4891,7 @@ ix86_gimplify_va_arg (tree valist, tree
|
|
||||||
{
|
|
||||||
int i, prev_size = 0;
|
|
||||||
tree temp = create_tmp_var (type, "va_arg_tmp");
|
|
||||||
+ TREE_ADDRESSABLE (temp) = 1;
|
|
||||||
|
|
||||||
/* addr = &temp; */
|
|
||||||
t = build1 (ADDR_EXPR, build_pointer_type (type), temp);
|
|
||||||
--- gcc/testsuite/gcc.dg/pr105331.c.jj 2022-04-21 12:09:34.398906718 +0200
|
|
||||||
+++ gcc/testsuite/gcc.dg/pr105331.c 2022-04-21 12:09:07.304283903 +0200
|
|
||||||
@@ -0,0 +1,11 @@
|
|
||||||
+/* PR target/105331 */
|
|
||||||
+/* { dg-do compile } */
|
|
||||||
+/* { dg-options "-O -Wuninitialized" } */
|
|
||||||
+
|
|
||||||
+#include <stdarg.h>
|
|
||||||
+
|
|
||||||
+int
|
|
||||||
+foo (va_list *va)
|
|
||||||
+{
|
|
||||||
+ return va_arg (*va, double _Complex); /* { dg-bogus "may be used uninitialized" } */
|
|
||||||
+}
|
|
@ -1,388 +0,0 @@
|
|||||||
commit c725028a8bb9478ec84332641147ad12b9236922
|
|
||||||
Author: Jonathan Wakely <jwakely@redhat.com>
|
|
||||||
Date: Tue Dec 14 14:32:35 2021 +0000
|
|
||||||
|
|
||||||
libstdc++: Fix handling of invalid ranges in std::regex [PR102447]
|
|
||||||
|
|
||||||
std::regex currently allows invalid bracket ranges such as [\w-a] which
|
|
||||||
are only allowed by ECMAScript when in web browser compatibility mode.
|
|
||||||
It should be an error, because the start of the range is a character
|
|
||||||
class, not a single character. The current implementation of
|
|
||||||
_Compiler::_M_expression_term does not provide a way to reject this,
|
|
||||||
because we only remember a previous character, not whether we just
|
|
||||||
processed a character class (or collating symbol etc.)
|
|
||||||
|
|
||||||
This patch replaces the pair<bool, CharT> used to emulate
|
|
||||||
optional<CharT> with a custom class closer to pair<tribool,CharT>. That
|
|
||||||
allows us to track three states, so that we can tell when we've just
|
|
||||||
seen a character class.
|
|
||||||
|
|
||||||
With this additional state the code in _M_expression_term for processing
|
|
||||||
the _S_token_bracket_dash can be improved to correctly reject the [\w-a]
|
|
||||||
case, without regressing for valid cases such as [\w-] and [----].
|
|
||||||
|
|
||||||
libstdc++-v3/ChangeLog:
|
|
||||||
|
|
||||||
PR libstdc++/102447
|
|
||||||
* include/bits/regex_compiler.h (_Compiler::_BracketState): New
|
|
||||||
class.
|
|
||||||
(_Compiler::_BrackeyMatcher): New alias template.
|
|
||||||
(_Compiler::_M_expression_term): Change pair<bool, CharT>
|
|
||||||
parameter to _BracketState. Process first character for
|
|
||||||
ECMAScript syntax as well as POSIX.
|
|
||||||
* include/bits/regex_compiler.tcc
|
|
||||||
(_Compiler::_M_insert_bracket_matcher): Pass _BracketState.
|
|
||||||
(_Compiler::_M_expression_term): Use _BracketState to store
|
|
||||||
state between calls. Improve handling of dashes in ranges.
|
|
||||||
* testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc:
|
|
||||||
Add more tests for ranges containing dashes. Check invalid
|
|
||||||
ranges with character class at the beginning.
|
|
||||||
|
|
||||||
(cherry picked from commit 7ce3c230edf6e498e125c805a6dd313bf87dc439)
|
|
||||||
|
|
||||||
diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h
|
|
||||||
index f224fcb06e0..aa19df2bf9a 100644
|
|
||||||
--- a/libstdc++-v3/include/bits/regex_compiler.h
|
|
||||||
+++ b/libstdc++-v3/include/bits/regex_compiler.h
|
|
||||||
@@ -122,13 +122,45 @@ namespace __detail
|
|
||||||
void
|
|
||||||
_M_insert_bracket_matcher(bool __neg);
|
|
||||||
|
|
||||||
- // Returns true if successfully matched one term and should continue.
|
|
||||||
+ // Cache of the last atom seen in a bracketed range expression.
|
|
||||||
+ struct _BracketState
|
|
||||||
+ {
|
|
||||||
+ enum class _Type : char { _None, _Char, _Class } _M_type = _Type::_None;
|
|
||||||
+ _CharT _M_char;
|
|
||||||
+
|
|
||||||
+ void
|
|
||||||
+ set(_CharT __c) noexcept { _M_type = _Type::_Char; _M_char = __c; }
|
|
||||||
+
|
|
||||||
+ _GLIBCXX_NODISCARD _CharT
|
|
||||||
+ get() const noexcept { return _M_char; }
|
|
||||||
+
|
|
||||||
+ void
|
|
||||||
+ reset(_Type __t = _Type::_None) noexcept { _M_type = __t; }
|
|
||||||
+
|
|
||||||
+ explicit operator bool() const noexcept
|
|
||||||
+ { return _M_type != _Type::_None; }
|
|
||||||
+
|
|
||||||
+ // Previous token was a single character.
|
|
||||||
+ _GLIBCXX_NODISCARD bool
|
|
||||||
+ _M_is_char() const noexcept { return _M_type == _Type::_Char; }
|
|
||||||
+
|
|
||||||
+ // Previous token was a character class, equivalent class,
|
|
||||||
+ // collating symbol etc.
|
|
||||||
+ _GLIBCXX_NODISCARD bool
|
|
||||||
+ _M_is_class() const noexcept { return _M_type == _Type::_Class; }
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ template<bool __icase, bool __collate>
|
|
||||||
+ using _BracketMatcher
|
|
||||||
+ = std::__detail::_BracketMatcher<_TraitsT, __icase, __collate>;
|
|
||||||
+
|
|
||||||
+ // Returns true if successfully parsed one term and should continue
|
|
||||||
+ // compiling a bracket expression.
|
|
||||||
// Returns false if the compiler should move on.
|
|
||||||
template<bool __icase, bool __collate>
|
|
||||||
bool
|
|
||||||
- _M_expression_term(pair<bool, _CharT>& __last_char,
|
|
||||||
- _BracketMatcher<_TraitsT, __icase, __collate>&
|
|
||||||
- __matcher);
|
|
||||||
+ _M_expression_term(_BracketState& __last_char,
|
|
||||||
+ _BracketMatcher<__icase, __collate>& __matcher);
|
|
||||||
|
|
||||||
int
|
|
||||||
_M_cur_int_value(int __radix);
|
|
||||||
diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc
|
|
||||||
index ea07bc2428e..7769a9e63a3 100644
|
|
||||||
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
|
|
||||||
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
|
|
||||||
@@ -403,7 +403,7 @@ namespace __detail
|
|
||||||
_M_insert_character_class_matcher()
|
|
||||||
{
|
|
||||||
__glibcxx_assert(_M_value.size() == 1);
|
|
||||||
- _BracketMatcher<_TraitsT, __icase, __collate> __matcher
|
|
||||||
+ _BracketMatcher<__icase, __collate> __matcher
|
|
||||||
(_M_ctype.is(_CtypeT::upper, _M_value[0]), _M_traits);
|
|
||||||
__matcher._M_add_character_class(_M_value, false);
|
|
||||||
__matcher._M_ready();
|
|
||||||
@@ -424,25 +424,17 @@ namespace __detail
|
|
||||||
_Compiler<_TraitsT>::
|
|
||||||
_M_insert_bracket_matcher(bool __neg)
|
|
||||||
{
|
|
||||||
- _BracketMatcher<_TraitsT, __icase, __collate> __matcher(__neg, _M_traits);
|
|
||||||
- pair<bool, _CharT> __last_char; // Optional<_CharT>
|
|
||||||
- __last_char.first = false;
|
|
||||||
- if (!(_M_flags & regex_constants::ECMAScript))
|
|
||||||
- {
|
|
||||||
- if (_M_try_char())
|
|
||||||
- {
|
|
||||||
- __last_char.first = true;
|
|
||||||
- __last_char.second = _M_value[0];
|
|
||||||
- }
|
|
||||||
- else if (_M_match_token(_ScannerT::_S_token_bracket_dash))
|
|
||||||
- {
|
|
||||||
- __last_char.first = true;
|
|
||||||
- __last_char.second = '-';
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- while (_M_expression_term(__last_char, __matcher));
|
|
||||||
- if (__last_char.first)
|
|
||||||
- __matcher._M_add_char(__last_char.second);
|
|
||||||
+ _BracketMatcher<__icase, __collate> __matcher(__neg, _M_traits);
|
|
||||||
+ _BracketState __last_char;
|
|
||||||
+ if (_M_try_char())
|
|
||||||
+ __last_char.set(_M_value[0]);
|
|
||||||
+ else if (_M_match_token(_ScannerT::_S_token_bracket_dash))
|
|
||||||
+ // Dash as first character is a normal character.
|
|
||||||
+ __last_char.set('-');
|
|
||||||
+ while (_M_expression_term(__last_char, __matcher))
|
|
||||||
+ ;
|
|
||||||
+ if (__last_char._M_is_char())
|
|
||||||
+ __matcher._M_add_char(__last_char.get());
|
|
||||||
__matcher._M_ready();
|
|
||||||
_M_stack.push(_StateSeqT(
|
|
||||||
*_M_nfa,
|
|
||||||
@@ -447,27 +438,27 @@ namespace __detail
|
|
||||||
template<bool __icase, bool __collate>
|
|
||||||
bool
|
|
||||||
_Compiler<_TraitsT>::
|
|
||||||
- _M_expression_term(pair<bool, _CharT>& __last_char,
|
|
||||||
- _BracketMatcher<_TraitsT, __icase, __collate>& __matcher)
|
|
||||||
+ _M_expression_term(_BracketState& __last_char,
|
|
||||||
+ _BracketMatcher<__icase, __collate>& __matcher)
|
|
||||||
{
|
|
||||||
if (_M_match_token(_ScannerT::_S_token_bracket_end))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
+ // Add any previously cached char into the matcher and update cache.
|
|
||||||
const auto __push_char = [&](_CharT __ch)
|
|
||||||
{
|
|
||||||
- if (__last_char.first)
|
|
||||||
- __matcher._M_add_char(__last_char.second);
|
|
||||||
- else
|
|
||||||
- __last_char.first = true;
|
|
||||||
- __last_char.second = __ch;
|
|
||||||
+ if (__last_char._M_is_char())
|
|
||||||
+ __matcher._M_add_char(__last_char.get());
|
|
||||||
+ __last_char.set(__ch);
|
|
||||||
};
|
|
||||||
- const auto __flush = [&]
|
|
||||||
+ // Add any previously cached char into the matcher and update cache.
|
|
||||||
+ const auto __push_class = [&]
|
|
||||||
{
|
|
||||||
- if (__last_char.first)
|
|
||||||
- {
|
|
||||||
- __matcher._M_add_char(__last_char.second);
|
|
||||||
- __last_char.first = false;
|
|
||||||
- }
|
|
||||||
+ if (__last_char._M_is_char())
|
|
||||||
+ __matcher._M_add_char(__last_char.get());
|
|
||||||
+ // We don't cache anything here, just record that the last thing
|
|
||||||
+ // processed was a character class (or similar).
|
|
||||||
+ __last_char.reset(_BracketState::_Type::_Class);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (_M_match_token(_ScannerT::_S_token_collsymbol))
|
|
||||||
@@ -476,16 +467,16 @@ namespace __detail
|
|
||||||
if (__symbol.size() == 1)
|
|
||||||
__push_char(__symbol[0]);
|
|
||||||
else
|
|
||||||
- __flush();
|
|
||||||
+ __push_class();
|
|
||||||
}
|
|
||||||
else if (_M_match_token(_ScannerT::_S_token_equiv_class_name))
|
|
||||||
{
|
|
||||||
- __flush();
|
|
||||||
+ __push_class();
|
|
||||||
__matcher._M_add_equivalence_class(_M_value);
|
|
||||||
}
|
|
||||||
else if (_M_match_token(_ScannerT::_S_token_char_class_name))
|
|
||||||
{
|
|
||||||
- __flush();
|
|
||||||
+ __push_class();
|
|
||||||
__matcher._M_add_character_class(_M_value, false);
|
|
||||||
}
|
|
||||||
else if (_M_try_char())
|
|
||||||
@@ -502,49 +493,50 @@ namespace __detail
|
|
||||||
// It turns out that no one reads BNFs ;)
|
|
||||||
else if (_M_match_token(_ScannerT::_S_token_bracket_dash))
|
|
||||||
{
|
|
||||||
- if (!__last_char.first)
|
|
||||||
+ if (_M_match_token(_ScannerT::_S_token_bracket_end))
|
|
||||||
{
|
|
||||||
- if (!(_M_flags & regex_constants::ECMAScript))
|
|
||||||
- {
|
|
||||||
- if (_M_match_token(_ScannerT::_S_token_bracket_end))
|
|
||||||
- {
|
|
||||||
- __push_char('-');
|
|
||||||
- return false;
|
|
||||||
- }
|
|
||||||
- __throw_regex_error(
|
|
||||||
- regex_constants::error_range,
|
|
||||||
- "Unexpected dash in bracket expression. For POSIX syntax, "
|
|
||||||
- "a dash is not treated literally only when it is at "
|
|
||||||
- "beginning or end.");
|
|
||||||
- }
|
|
||||||
+ // For "-]" the dash is a literal character.
|
|
||||||
__push_char('-');
|
|
||||||
+ return false;
|
|
||||||
}
|
|
||||||
- else
|
|
||||||
+ else if (__last_char._M_is_class())
|
|
||||||
+ {
|
|
||||||
+ // "\\w-" is invalid, start of range must be a single char.
|
|
||||||
+ __throw_regex_error(regex_constants::error_range,
|
|
||||||
+ "Invalid start of range in bracket expression.");
|
|
||||||
+ }
|
|
||||||
+ else if (__last_char._M_is_char())
|
|
||||||
{
|
|
||||||
if (_M_try_char())
|
|
||||||
{
|
|
||||||
- __matcher._M_make_range(__last_char.second, _M_value[0]);
|
|
||||||
- __last_char.first = false;
|
|
||||||
+ // "x-y"
|
|
||||||
+ __matcher._M_make_range(__last_char.get(), _M_value[0]);
|
|
||||||
+ __last_char.reset();
|
|
||||||
}
|
|
||||||
else if (_M_match_token(_ScannerT::_S_token_bracket_dash))
|
|
||||||
{
|
|
||||||
- __matcher._M_make_range(__last_char.second, '-');
|
|
||||||
- __last_char.first = false;
|
|
||||||
+ // "x--"
|
|
||||||
+ __matcher._M_make_range(__last_char.get(), '-');
|
|
||||||
+ __last_char.reset();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
- {
|
|
||||||
- if (_M_scanner._M_get_token()
|
|
||||||
- != _ScannerT::_S_token_bracket_end)
|
|
||||||
- __throw_regex_error(
|
|
||||||
- regex_constants::error_range,
|
|
||||||
- "Character is expected after a dash.");
|
|
||||||
- __push_char('-');
|
|
||||||
- }
|
|
||||||
+ __throw_regex_error(regex_constants::error_range,
|
|
||||||
+ "Invalid end of range in bracket expression.");
|
|
||||||
}
|
|
||||||
+ else if (_M_flags & regex_constants::ECMAScript)
|
|
||||||
+ {
|
|
||||||
+ // A dash that is not part of an existing range. Might be the
|
|
||||||
+ // start of a new range, or might just be a literal '-' char.
|
|
||||||
+ // Only ECMAScript allows that in the middle of a bracket expr.
|
|
||||||
+ __push_char('-');
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ __throw_regex_error(regex_constants::error_range,
|
|
||||||
+ "Invalid dash in bracket expression.");
|
|
||||||
}
|
|
||||||
else if (_M_match_token(_ScannerT::_S_token_quoted_class))
|
|
||||||
{
|
|
||||||
- __flush();
|
|
||||||
+ __push_class();
|
|
||||||
__matcher._M_add_character_class(_M_value,
|
|
||||||
_M_ctype.is(_CtypeT::upper,
|
|
||||||
_M_value[0]));
|
|
||||||
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc
|
|
||||||
index 7df70604ea6..0d76e63da7b 100644
|
|
||||||
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc
|
|
||||||
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc
|
|
||||||
@@ -69,6 +69,16 @@ test01()
|
|
||||||
void
|
|
||||||
test02()
|
|
||||||
{
|
|
||||||
+ VERIFY(regex_match("-", regex("[-]", regex_constants::ECMAScript)));
|
|
||||||
+ VERIFY(regex_match("-", regex("[--]", regex_constants::ECMAScript)));
|
|
||||||
+ VERIFY(regex_match("-", regex("[---]", regex_constants::ECMAScript)));
|
|
||||||
+ VERIFY(regex_match("-", regex("[----]", regex_constants::ECMAScript)));
|
|
||||||
+ VERIFY(regex_match("-", regex("[-----]", regex_constants::ECMAScript)));
|
|
||||||
+
|
|
||||||
+ VERIFY(regex_match("-", regex("[-]", regex_constants::extended)));
|
|
||||||
+ VERIFY(regex_match("-", regex("[--]", regex_constants::extended)));
|
|
||||||
+ VERIFY(regex_match("-", regex("[---]", regex_constants::extended)));
|
|
||||||
+ VERIFY(regex_match("-", regex("[----]", regex_constants::extended)));
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::regex re("[-----]", std::regex::extended);
|
|
||||||
@@ -78,7 +88,6 @@ test02()
|
|
||||||
{
|
|
||||||
VERIFY(e.code() == std::regex_constants::error_range);
|
|
||||||
}
|
|
||||||
- std::regex re("[-----]", std::regex::ECMAScript);
|
|
||||||
|
|
||||||
VERIFY(!regex_match("b", regex("[-ac]", regex_constants::extended)));
|
|
||||||
VERIFY(!regex_match("b", regex("[ac-]", regex_constants::extended)));
|
|
||||||
@@ -93,7 +102,27 @@ test02()
|
|
||||||
}
|
|
||||||
catch (const std::regex_error& e)
|
|
||||||
{
|
|
||||||
+ VERIFY(e.code() == std::regex_constants::error_range);
|
|
||||||
+ }
|
|
||||||
+ try
|
|
||||||
+ {
|
|
||||||
+ regex("[@--]", regex_constants::extended);
|
|
||||||
+ VERIFY(false);
|
|
||||||
}
|
|
||||||
+ catch (const std::regex_error& e)
|
|
||||||
+ {
|
|
||||||
+ VERIFY(e.code() == std::regex_constants::error_range);
|
|
||||||
+ }
|
|
||||||
+ try
|
|
||||||
+ {
|
|
||||||
+ regex("[--%]", regex_constants::extended);
|
|
||||||
+ VERIFY(false);
|
|
||||||
+ }
|
|
||||||
+ catch (const std::regex_error& e)
|
|
||||||
+ {
|
|
||||||
+ VERIFY(e.code() == std::regex_constants::error_range);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
VERIFY(regex_match("].", regex("[][.hyphen.]-0]*", regex_constants::extended)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -158,6 +187,36 @@ test06()
|
|
||||||
VERIFY(regex_match("a-", debian_cron_namespace_ok));
|
|
||||||
}
|
|
||||||
|
|
||||||
+// libstdc++/102447
|
|
||||||
+void
|
|
||||||
+test07()
|
|
||||||
+{
|
|
||||||
+ VERIFY(regex_match("-", std::regex("[\\w-]", std::regex::ECMAScript)));
|
|
||||||
+ VERIFY(regex_match("a", std::regex("[\\w-]", std::regex::ECMAScript)));
|
|
||||||
+ VERIFY(regex_match("-", std::regex("[a-]", std::regex::ECMAScript)));
|
|
||||||
+ VERIFY(regex_match("a", std::regex("[a-]", std::regex::ECMAScript)));
|
|
||||||
+
|
|
||||||
+ try
|
|
||||||
+ {
|
|
||||||
+ std::regex re("[\\w-a]", std::regex::ECMAScript);
|
|
||||||
+ VERIFY(false);
|
|
||||||
+ }
|
|
||||||
+ catch (const std::regex_error& e)
|
|
||||||
+ {
|
|
||||||
+ VERIFY(e.code() == std::regex_constants::error_range);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ try
|
|
||||||
+ {
|
|
||||||
+ std::regex re("[\\w--]", std::regex::ECMAScript);
|
|
||||||
+ VERIFY(false);
|
|
||||||
+ }
|
|
||||||
+ catch (const std::regex_error& e)
|
|
||||||
+ {
|
|
||||||
+ VERIFY(e.code() == std::regex_constants::error_range);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int
|
|
||||||
main()
|
|
||||||
{
|
|
||||||
@@ -167,6 +226,7 @@ main()
|
|
||||||
test04();
|
|
||||||
test05();
|
|
||||||
test06();
|
|
||||||
+ test07();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -0,0 +1,91 @@
|
|||||||
|
commit ef5f7b89bbc352255595069eb870d6f30f1f9134
|
||||||
|
Author: Andreas Krebbel <krebbel@linux.ibm.com>
|
||||||
|
Date: Wed Feb 1 08:59:41 2023 +0100
|
||||||
|
|
||||||
|
New reg note REG_CFA_NORESTORE
|
||||||
|
|
||||||
|
This patch introduces a new reg note which can be used to tell the CFI
|
||||||
|
verification in dwarf2cfi that a register is stored without intending
|
||||||
|
to restore from it.
|
||||||
|
|
||||||
|
This is useful when storing e.g. register contents to the stack and
|
||||||
|
generate CFI for it although the register is not really supposed to be
|
||||||
|
restored.
|
||||||
|
|
||||||
|
gcc/ChangeLog:
|
||||||
|
|
||||||
|
* dwarf2cfi.c (dwarf2out_frame_debug_cfa_restore): Add
|
||||||
|
EMIT_CFI parameter.
|
||||||
|
(dwarf2out_frame_debug): Add case for REG_CFA_NORESTORE.
|
||||||
|
* reg-notes.def (REG_CFA_NOTE): New reg note definition.
|
||||||
|
|
||||||
|
--- a/gcc/dwarf2cfi.c
|
||||||
|
+++ b/gcc/dwarf2cfi.c
|
||||||
|
@@ -1496,10 +1496,12 @@ dwarf2out_frame_debug_cfa_val_expression (rtx set)
|
||||||
|
update_row_reg_save (cur_row, dwf_regno (dest), cfi);
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE note. */
|
||||||
|
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE
|
||||||
|
+ note. When called with EMIT_CFI set to false emitting a CFI
|
||||||
|
+ statement is suppressed. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
-dwarf2out_frame_debug_cfa_restore (rtx reg)
|
||||||
|
+dwarf2out_frame_debug_cfa_restore (rtx reg, bool emit_cfi)
|
||||||
|
{
|
||||||
|
gcc_assert (REG_P (reg));
|
||||||
|
|
||||||
|
@@ -1507,7 +1509,8 @@ dwarf2out_frame_debug_cfa_restore (rtx reg)
|
||||||
|
if (!span)
|
||||||
|
{
|
||||||
|
unsigned int regno = dwf_regno (reg);
|
||||||
|
- add_cfi_restore (regno);
|
||||||
|
+ if (emit_cfi)
|
||||||
|
+ add_cfi_restore (regno);
|
||||||
|
update_row_reg_save (cur_row, regno, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
@@ -1522,7 +1525,8 @@ dwarf2out_frame_debug_cfa_restore (rtx reg)
|
||||||
|
reg = XVECEXP (span, 0, par_index);
|
||||||
|
gcc_assert (REG_P (reg));
|
||||||
|
unsigned int regno = dwf_regno (reg);
|
||||||
|
- add_cfi_restore (regno);
|
||||||
|
+ if (emit_cfi)
|
||||||
|
+ add_cfi_restore (regno);
|
||||||
|
update_row_reg_save (cur_row, regno, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -2309,6 +2313,7 @@ dwarf2out_frame_debug (rtx_insn *insn)
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REG_CFA_RESTORE:
|
||||||
|
+ case REG_CFA_NO_RESTORE:
|
||||||
|
n = XEXP (note, 0);
|
||||||
|
if (n == NULL)
|
||||||
|
{
|
||||||
|
@@ -2317,7 +2322,7 @@ dwarf2out_frame_debug (rtx_insn *insn)
|
||||||
|
n = XVECEXP (n, 0, 0);
|
||||||
|
n = XEXP (n, 0);
|
||||||
|
}
|
||||||
|
- dwarf2out_frame_debug_cfa_restore (n);
|
||||||
|
+ dwarf2out_frame_debug_cfa_restore (n, REG_NOTE_KIND (note) == REG_CFA_RESTORE);
|
||||||
|
handled_one = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
|
||||||
|
index 23de1f13ee9..1f74a605b3e 100644
|
||||||
|
--- a/gcc/reg-notes.def
|
||||||
|
+++ b/gcc/reg-notes.def
|
||||||
|
@@ -157,6 +157,11 @@ REG_CFA_NOTE (CFA_VAL_EXPRESSION)
|
||||||
|
first pattern is the register to be restored. */
|
||||||
|
REG_CFA_NOTE (CFA_RESTORE)
|
||||||
|
|
||||||
|
+/* Like CFA_RESTORE but without actually emitting CFI. This can be
|
||||||
|
+ used to tell the verification infrastructure that a register is
|
||||||
|
+ saved without intending to restore it. */
|
||||||
|
+REG_CFA_NOTE (CFA_NO_RESTORE)
|
||||||
|
+
|
||||||
|
/* Attached to insns that are RTX_FRAME_RELATED_P, marks insn that sets
|
||||||
|
vDRAP from DRAP. If vDRAP is a register, vdrap_reg is initalized
|
||||||
|
to the argument, if it is a MEM, it is ignored. */
|
@ -0,0 +1,92 @@
|
|||||||
|
commit 36ffb2e0293d1bbef30e3553a431679de00549b9
|
||||||
|
Author: Andreas Krebbel <krebbel@linux.ibm.com>
|
||||||
|
Date: Wed Feb 1 08:59:42 2023 +0100
|
||||||
|
|
||||||
|
IBM zSystems: Make stack_tie to work with hard frame pointer
|
||||||
|
|
||||||
|
With this patch a scheduling barrier is created to prevent the insn
|
||||||
|
setting up the frame-pointer and instructions which save GPRs to the
|
||||||
|
stack to be swapped. Otherwise broken CFI information would be
|
||||||
|
generated since the stack save insns would use a base register which
|
||||||
|
is not currently declared as holding the CFA.
|
||||||
|
|
||||||
|
Without -mpreserve-args this did not happen because the store multiple
|
||||||
|
we used for saving the GPRs would also cover the frame-pointer
|
||||||
|
register and therefore creates a dependency on the frame-pointer
|
||||||
|
hardreg. However, with this patch the stack_tie is emitted regardless
|
||||||
|
of -mpreserve-args since this in general appears to be the safer
|
||||||
|
approach.
|
||||||
|
|
||||||
|
* config/s390/s390.c (save_gprs): Use gen_frame_mem.
|
||||||
|
(restore_gprs): Likewise.
|
||||||
|
(s390_emit_stack_tie): Make the stack_tie to be dependent on the
|
||||||
|
frame pointer if a frame-pointer is used.
|
||||||
|
(s390_emit_prologue): Emit stack_tie when frame-pointer is needed.
|
||||||
|
* config/s390/s390.md (stack_tie): Add a register operand and
|
||||||
|
rename to ...
|
||||||
|
(@stack_tie<mode>): ... this.
|
||||||
|
|
||||||
|
--- a/gcc/config/s390/s390.c
|
||||||
|
+++ b/gcc/config/s390/s390.c
|
||||||
|
@@ -10898,9 +10898,7 @@ save_gprs (rtx base, int offset, int first, int last)
|
||||||
|
int i;
|
||||||
|
|
||||||
|
addr = plus_constant (Pmode, base, offset);
|
||||||
|
- addr = gen_rtx_MEM (Pmode, addr);
|
||||||
|
-
|
||||||
|
- set_mem_alias_set (addr, get_frame_alias_set ());
|
||||||
|
+ addr = gen_frame_mem (Pmode, addr);
|
||||||
|
|
||||||
|
/* Special-case single register. */
|
||||||
|
if (first == last)
|
||||||
|
@@ -11012,8 +11010,7 @@ restore_gprs (rtx base, int offset, int first, int last)
|
||||||
|
rtx addr, insn;
|
||||||
|
|
||||||
|
addr = plus_constant (Pmode, base, offset);
|
||||||
|
- addr = gen_rtx_MEM (Pmode, addr);
|
||||||
|
- set_mem_alias_set (addr, get_frame_alias_set ());
|
||||||
|
+ addr = gen_frame_mem (Pmode, addr);
|
||||||
|
|
||||||
|
/* Special-case single register. */
|
||||||
|
if (first == last)
|
||||||
|
@@ -11062,10 +11059,11 @@ s390_load_got (void)
|
||||||
|
static void
|
||||||
|
s390_emit_stack_tie (void)
|
||||||
|
{
|
||||||
|
- rtx mem = gen_frame_mem (BLKmode,
|
||||||
|
- gen_rtx_REG (Pmode, STACK_POINTER_REGNUM));
|
||||||
|
-
|
||||||
|
- emit_insn (gen_stack_tie (mem));
|
||||||
|
+ rtx mem = gen_frame_mem (BLKmode, stack_pointer_rtx);
|
||||||
|
+ if (frame_pointer_needed)
|
||||||
|
+ emit_insn (gen_stack_tie (Pmode, mem, hard_frame_pointer_rtx));
|
||||||
|
+ else
|
||||||
|
+ emit_insn (gen_stack_tie (Pmode, mem, stack_pointer_rtx));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy GPRS into FPR save slots. */
|
||||||
|
@@ -11676,6 +11674,7 @@ s390_emit_prologue (void)
|
||||||
|
|
||||||
|
if (frame_pointer_needed)
|
||||||
|
{
|
||||||
|
+ s390_emit_stack_tie ();
|
||||||
|
insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
|
||||||
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
}
|
||||||
|
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
|
||||||
|
index 4828aa08be6..00d39608e1d 100644
|
||||||
|
--- a/gcc/config/s390/s390.md
|
||||||
|
+++ b/gcc/config/s390/s390.md
|
||||||
|
@@ -11590,9 +11590,10 @@ (define_insn "stack_protect_test<mode>"
|
||||||
|
; This is used in s390_emit_prologue in order to prevent insns
|
||||||
|
; adjusting the stack pointer to be moved over insns writing stack
|
||||||
|
; slots using a copy of the stack pointer in a different register.
|
||||||
|
-(define_insn "stack_tie"
|
||||||
|
+(define_insn "@stack_tie<mode>"
|
||||||
|
[(set (match_operand:BLK 0 "memory_operand" "+m")
|
||||||
|
- (unspec:BLK [(match_dup 0)] UNSPEC_TIE))]
|
||||||
|
+ (unspec:BLK [(match_dup 0)
|
||||||
|
+ (match_operand:P 1 "register_operand" "r")] UNSPEC_TIE))]
|
||||||
|
""
|
||||||
|
""
|
||||||
|
[(set_attr "length" "0")])
|
@ -0,0 +1,545 @@
|
|||||||
|
commit 8091199cdf4d0aa9c28e4526548ddc25d02898ca
|
||||||
|
Author: Andreas Krebbel <krebbel@linux.ibm.com>
|
||||||
|
Date: Wed Feb 1 08:59:42 2023 +0100
|
||||||
|
|
||||||
|
IBM zSystems: Save argument registers to the stack -mpreserve-args
|
||||||
|
|
||||||
|
This adds support for preserving the content of parameter registers to
|
||||||
|
the stack and emit CFI for it. This useful for applications which want
|
||||||
|
to implement their own stack unwinding and need access to function
|
||||||
|
arguments.
|
||||||
|
|
||||||
|
With the -mpreserve-args option GPRs and FPRs are save to the stack
|
||||||
|
slots which are reserved for stdargs in the register save area.
|
||||||
|
|
||||||
|
gcc/ChangeLog:
|
||||||
|
|
||||||
|
* config/s390/s390.c (s390_restore_gpr_p): New function.
|
||||||
|
(s390_preserve_gpr_arg_in_range_p): New function.
|
||||||
|
(s390_preserve_gpr_arg_p): New function.
|
||||||
|
(s390_preserve_fpr_arg_p): New function.
|
||||||
|
(s390_register_info_stdarg_fpr): Rename to ...
|
||||||
|
(s390_register_info_arg_fpr): ... this. Add -mpreserve-args handling.
|
||||||
|
(s390_register_info_stdarg_gpr): Rename to ...
|
||||||
|
(s390_register_info_arg_gpr): ... this. Add -mpreserve-args handling.
|
||||||
|
(s390_register_info): Use the renamed functions above.
|
||||||
|
(s390_optimize_register_info): Likewise.
|
||||||
|
(save_fpr): Generate CFI for -mpreserve-args.
|
||||||
|
(save_gprs): Generate CFI for -mpreserve-args. Drop return value.
|
||||||
|
(s390_emit_prologue): Adjust to changed calling convention of save_gprs.
|
||||||
|
(s390_optimize_prologue): Likewise.
|
||||||
|
* config/s390/s390.opt: New option -mpreserve-args
|
||||||
|
|
||||||
|
gcc/testsuite/ChangeLog:
|
||||||
|
|
||||||
|
* gcc.target/s390/preserve-args-1.c: New test.
|
||||||
|
* gcc.target/s390/preserve-args-2.c: New test.
|
||||||
|
|
||||||
|
--- a/gcc/config/s390/s390.c
|
||||||
|
+++ b/gcc/config/s390/s390.c
|
||||||
|
@@ -411,6 +411,45 @@ struct s390_address
|
||||||
|
#define FP_ARG_NUM_REG (TARGET_64BIT? 4 : 2)
|
||||||
|
#define VEC_ARG_NUM_REG 8
|
||||||
|
|
||||||
|
+/* Return TRUE if GPR REGNO is supposed to be restored in the function
|
||||||
|
+ epilogue. */
|
||||||
|
+static inline bool
|
||||||
|
+s390_restore_gpr_p (int regno)
|
||||||
|
+{
|
||||||
|
+ return (cfun_frame_layout.first_restore_gpr != -1
|
||||||
|
+ && regno >= cfun_frame_layout.first_restore_gpr
|
||||||
|
+ && regno <= cfun_frame_layout.last_restore_gpr);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Return TRUE if any of the registers in range [FIRST, LAST] is saved
|
||||||
|
+ because of -mpreserve-args. */
|
||||||
|
+static inline bool
|
||||||
|
+s390_preserve_gpr_arg_in_range_p (int first, int last)
|
||||||
|
+{
|
||||||
|
+ int num_arg_regs = MIN (crtl->args.info.gprs + cfun->va_list_gpr_size,
|
||||||
|
+ GP_ARG_NUM_REG);
|
||||||
|
+ return (num_arg_regs
|
||||||
|
+ && s390_preserve_args_p
|
||||||
|
+ && first <= GPR2_REGNUM + num_arg_regs - 1
|
||||||
|
+ && last >= GPR2_REGNUM);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline bool
|
||||||
|
+s390_preserve_gpr_arg_p (int regno)
|
||||||
|
+{
|
||||||
|
+ return s390_preserve_gpr_arg_in_range_p (regno, regno);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline bool
|
||||||
|
+s390_preserve_fpr_arg_p (int regno)
|
||||||
|
+{
|
||||||
|
+ int num_arg_regs = MIN (crtl->args.info.fprs + cfun->va_list_fpr_size,
|
||||||
|
+ FP_ARG_NUM_REG);
|
||||||
|
+ return (s390_preserve_args_p
|
||||||
|
+ && regno <= FPR0_REGNUM + num_arg_regs - 1
|
||||||
|
+ && regno >= FPR0_REGNUM);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* A couple of shortcuts. */
|
||||||
|
#define CONST_OK_FOR_J(x) \
|
||||||
|
CONST_OK_FOR_CONSTRAINT_P((x), 'J', "J")
|
||||||
|
@@ -9893,61 +9932,89 @@ s390_register_info_gprtofpr ()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the bits in fpr_bitmap for FPRs which need to be saved due to
|
||||||
|
- stdarg.
|
||||||
|
+ stdarg or -mpreserve-args.
|
||||||
|
This is a helper routine for s390_register_info. */
|
||||||
|
-
|
||||||
|
static void
|
||||||
|
-s390_register_info_stdarg_fpr ()
|
||||||
|
+s390_register_info_arg_fpr ()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
- int min_fpr;
|
||||||
|
- int max_fpr;
|
||||||
|
+ int min_stdarg_fpr = INT_MAX, max_stdarg_fpr = -1;
|
||||||
|
+ int min_preserve_fpr = INT_MAX, max_preserve_fpr = -1;
|
||||||
|
+ int min_fpr, max_fpr;
|
||||||
|
|
||||||
|
/* Save the FP argument regs for stdarg. f0, f2 for 31 bit and
|
||||||
|
f0-f4 for 64 bit. */
|
||||||
|
- if (!cfun->stdarg
|
||||||
|
- || !TARGET_HARD_FLOAT
|
||||||
|
- || !cfun->va_list_fpr_size
|
||||||
|
- || crtl->args.info.fprs >= FP_ARG_NUM_REG)
|
||||||
|
- return;
|
||||||
|
+ if (cfun->stdarg
|
||||||
|
+ && TARGET_HARD_FLOAT
|
||||||
|
+ && cfun->va_list_fpr_size
|
||||||
|
+ && crtl->args.info.fprs < FP_ARG_NUM_REG)
|
||||||
|
+ {
|
||||||
|
+ min_stdarg_fpr = crtl->args.info.fprs;
|
||||||
|
+ max_stdarg_fpr = min_stdarg_fpr + cfun->va_list_fpr_size - 1;
|
||||||
|
+ if (max_stdarg_fpr >= FP_ARG_NUM_REG)
|
||||||
|
+ max_stdarg_fpr = FP_ARG_NUM_REG - 1;
|
||||||
|
+
|
||||||
|
+ /* FPR argument regs start at f0. */
|
||||||
|
+ min_stdarg_fpr += FPR0_REGNUM;
|
||||||
|
+ max_stdarg_fpr += FPR0_REGNUM;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- min_fpr = crtl->args.info.fprs;
|
||||||
|
- max_fpr = min_fpr + cfun->va_list_fpr_size - 1;
|
||||||
|
- if (max_fpr >= FP_ARG_NUM_REG)
|
||||||
|
- max_fpr = FP_ARG_NUM_REG - 1;
|
||||||
|
+ if (s390_preserve_args_p && crtl->args.info.fprs)
|
||||||
|
+ {
|
||||||
|
+ min_preserve_fpr = FPR0_REGNUM;
|
||||||
|
+ max_preserve_fpr = MIN (FPR0_REGNUM + FP_ARG_NUM_REG - 1,
|
||||||
|
+ FPR0_REGNUM + crtl->args.info.fprs - 1);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- /* FPR argument regs start at f0. */
|
||||||
|
- min_fpr += FPR0_REGNUM;
|
||||||
|
- max_fpr += FPR0_REGNUM;
|
||||||
|
+ min_fpr = MIN (min_stdarg_fpr, min_preserve_fpr);
|
||||||
|
+ max_fpr = MAX (max_stdarg_fpr, max_preserve_fpr);
|
||||||
|
+
|
||||||
|
+ if (max_fpr == -1)
|
||||||
|
+ return;
|
||||||
|
|
||||||
|
for (i = min_fpr; i <= max_fpr; i++)
|
||||||
|
cfun_set_fpr_save (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
+
|
||||||
|
/* Reserve the GPR save slots for GPRs which need to be saved due to
|
||||||
|
- stdarg.
|
||||||
|
+ stdarg or -mpreserve-args.
|
||||||
|
This is a helper routine for s390_register_info. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
-s390_register_info_stdarg_gpr ()
|
||||||
|
+s390_register_info_arg_gpr ()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
- int min_gpr;
|
||||||
|
- int max_gpr;
|
||||||
|
+ int min_stdarg_gpr = INT_MAX, max_stdarg_gpr = -1;
|
||||||
|
+ int min_preserve_gpr = INT_MAX, max_preserve_gpr = -1;
|
||||||
|
+ int min_gpr, max_gpr;
|
||||||
|
|
||||||
|
- if (!cfun->stdarg
|
||||||
|
- || !cfun->va_list_gpr_size
|
||||||
|
- || crtl->args.info.gprs >= GP_ARG_NUM_REG)
|
||||||
|
- return;
|
||||||
|
+ if (cfun->stdarg
|
||||||
|
+ && cfun->va_list_gpr_size
|
||||||
|
+ && crtl->args.info.gprs < GP_ARG_NUM_REG)
|
||||||
|
+ {
|
||||||
|
+ min_stdarg_gpr = crtl->args.info.gprs;
|
||||||
|
+ max_stdarg_gpr = min_stdarg_gpr + cfun->va_list_gpr_size - 1;
|
||||||
|
+ if (max_stdarg_gpr >= GP_ARG_NUM_REG)
|
||||||
|
+ max_stdarg_gpr = GP_ARG_NUM_REG - 1;
|
||||||
|
+
|
||||||
|
+ /* GPR argument regs start at r2. */
|
||||||
|
+ min_stdarg_gpr += GPR2_REGNUM;
|
||||||
|
+ max_stdarg_gpr += GPR2_REGNUM;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (s390_preserve_args_p && crtl->args.info.gprs)
|
||||||
|
+ {
|
||||||
|
+ min_preserve_gpr = GPR2_REGNUM;
|
||||||
|
+ max_preserve_gpr = MIN (GPR6_REGNUM,
|
||||||
|
+ GPR2_REGNUM + crtl->args.info.gprs - 1);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- min_gpr = crtl->args.info.gprs;
|
||||||
|
- max_gpr = min_gpr + cfun->va_list_gpr_size - 1;
|
||||||
|
- if (max_gpr >= GP_ARG_NUM_REG)
|
||||||
|
- max_gpr = GP_ARG_NUM_REG - 1;
|
||||||
|
+ min_gpr = MIN (min_stdarg_gpr, min_preserve_gpr);
|
||||||
|
+ max_gpr = MAX (max_stdarg_gpr, max_preserve_gpr);
|
||||||
|
|
||||||
|
- /* GPR argument regs start at r2. */
|
||||||
|
- min_gpr += GPR2_REGNUM;
|
||||||
|
- max_gpr += GPR2_REGNUM;
|
||||||
|
+ if (max_gpr == -1)
|
||||||
|
+ return;
|
||||||
|
|
||||||
|
/* If r6 was supposed to be saved into an FPR and now needs to go to
|
||||||
|
the stack for vararg we have to adjust the restore range to make
|
||||||
|
@@ -10079,14 +10146,14 @@ s390_register_info ()
|
||||||
|
if (clobbered_regs[i])
|
||||||
|
cfun_gpr_save_slot (i) = SAVE_SLOT_STACK;
|
||||||
|
|
||||||
|
- s390_register_info_stdarg_fpr ();
|
||||||
|
+ s390_register_info_arg_fpr ();
|
||||||
|
s390_register_info_gprtofpr ();
|
||||||
|
s390_register_info_set_ranges ();
|
||||||
|
- /* stdarg functions might need to save GPRs 2 to 6. This might
|
||||||
|
- override the GPR->FPR save decision made by
|
||||||
|
- s390_register_info_gprtofpr for r6 since vararg regs must go to
|
||||||
|
- the stack. */
|
||||||
|
- s390_register_info_stdarg_gpr ();
|
||||||
|
+
|
||||||
|
+ /* Forcing argument registers to be saved on the stack might
|
||||||
|
+ override the GPR->FPR save decision for r6 so this must come
|
||||||
|
+ last. */
|
||||||
|
+ s390_register_info_arg_gpr ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if REGNO is a global register, but not one
|
||||||
|
@@ -10141,7 +10208,7 @@ s390_optimize_register_info ()
|
||||||
|
cfun_gpr_save_slot (i) = SAVE_SLOT_NONE;
|
||||||
|
|
||||||
|
s390_register_info_set_ranges ();
|
||||||
|
- s390_register_info_stdarg_gpr ();
|
||||||
|
+ s390_register_info_arg_gpr ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill cfun->machine with info about frame of current function. */
|
||||||
|
@@ -10864,14 +10931,28 @@ static rtx
|
||||||
|
save_fpr (rtx base, int offset, int regnum)
|
||||||
|
{
|
||||||
|
rtx addr;
|
||||||
|
+ rtx insn;
|
||||||
|
+
|
||||||
|
addr = gen_rtx_MEM (DFmode, plus_constant (Pmode, base, offset));
|
||||||
|
|
||||||
|
- if (regnum >= 16 && regnum <= (16 + FP_ARG_NUM_REG))
|
||||||
|
+ if (regnum >= FPR0_REGNUM && regnum <= (FPR0_REGNUM + FP_ARG_NUM_REG))
|
||||||
|
set_mem_alias_set (addr, get_varargs_alias_set ());
|
||||||
|
else
|
||||||
|
set_mem_alias_set (addr, get_frame_alias_set ());
|
||||||
|
|
||||||
|
- return emit_move_insn (addr, gen_rtx_REG (DFmode, regnum));
|
||||||
|
+ insn = emit_move_insn (addr, gen_rtx_REG (DFmode, regnum));
|
||||||
|
+
|
||||||
|
+ if (!call_used_regs[regnum] || s390_preserve_fpr_arg_p (regnum))
|
||||||
|
+ RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
+
|
||||||
|
+ if (s390_preserve_fpr_arg_p (regnum) && !cfun_fpr_save_p (regnum))
|
||||||
|
+ {
|
||||||
|
+ rtx reg = gen_rtx_REG (DFmode, regnum);
|
||||||
|
+ add_reg_note (insn, REG_CFA_NO_RESTORE, reg);
|
||||||
|
+ add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (addr, reg));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return insn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emit insn to restore fpr REGNUM from offset OFFSET relative
|
||||||
|
@@ -10891,10 +10972,11 @@ restore_fpr (rtx base, int offset, int regnum)
|
||||||
|
the register save area located at offset OFFSET
|
||||||
|
relative to register BASE. */
|
||||||
|
|
||||||
|
-static rtx
|
||||||
|
-save_gprs (rtx base, int offset, int first, int last)
|
||||||
|
+static void
|
||||||
|
+save_gprs (rtx base, int offset, int first, int last, rtx_insn *before = NULL)
|
||||||
|
{
|
||||||
|
rtx addr, insn, note;
|
||||||
|
+ rtx_insn *out_insn;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
addr = plus_constant (Pmode, base, offset);
|
||||||
|
@@ -10910,7 +10992,15 @@ save_gprs (rtx base, int offset, int first, int last)
|
||||||
|
|
||||||
|
if (!global_not_special_regno_p (first))
|
||||||
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
- return insn;
|
||||||
|
+
|
||||||
|
+ if (s390_preserve_gpr_arg_p (first) && !s390_restore_gpr_p (first))
|
||||||
|
+ {
|
||||||
|
+ rtx reg = gen_rtx_REG (Pmode, first);
|
||||||
|
+ add_reg_note (insn, REG_CFA_NO_RESTORE, reg);
|
||||||
|
+ add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (addr, reg));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ goto emit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -10939,7 +11029,12 @@ save_gprs (rtx base, int offset, int first, int last)
|
||||||
|
set, even if it does not. Therefore we emit a new pattern
|
||||||
|
without those registers as REG_FRAME_RELATED_EXPR note. */
|
||||||
|
|
||||||
|
- if (first >= 6 && !global_not_special_regno_p (first))
|
||||||
|
+ /* In these cases all of the sets are marked as frame related:
|
||||||
|
+ 1. call-save GPR saved and restored
|
||||||
|
+ 2. argument GPR saved because of -mpreserve-args */
|
||||||
|
+ if ((first >= GPR6_REGNUM && !global_not_special_regno_p (first))
|
||||||
|
+ || s390_preserve_gpr_arg_in_range_p (first, last))
|
||||||
|
+
|
||||||
|
{
|
||||||
|
rtx pat = PATTERN (insn);
|
||||||
|
|
||||||
|
@@ -10950,6 +11045,24 @@ save_gprs (rtx base, int offset, int first, int last)
|
||||||
|
RTX_FRAME_RELATED_P (XVECEXP (pat, 0, i)) = 1;
|
||||||
|
|
||||||
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
+
|
||||||
|
+ /* For the -mpreserve-args register saves no restore operations
|
||||||
|
+ will be emitted. CFI checking would complain about this. We
|
||||||
|
+ manually generate the REG_CFA notes here to be able to mark
|
||||||
|
+ those operations with REG_CFA_NO_RESTORE. */
|
||||||
|
+ if (s390_preserve_gpr_arg_in_range_p (first, last))
|
||||||
|
+ {
|
||||||
|
+ for (int regno = first; regno <= last; regno++)
|
||||||
|
+ {
|
||||||
|
+ rtx reg = gen_rtx_REG (Pmode, regno);
|
||||||
|
+ rtx reg_addr = plus_constant (Pmode, base,
|
||||||
|
+ offset + (regno - first) * UNITS_PER_LONG);
|
||||||
|
+ if (!s390_restore_gpr_p (regno))
|
||||||
|
+ add_reg_note (insn, REG_CFA_NO_RESTORE, reg);
|
||||||
|
+ add_reg_note (insn, REG_CFA_OFFSET,
|
||||||
|
+ gen_rtx_SET (gen_frame_mem (Pmode, reg_addr), reg));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
else if (last >= 6)
|
||||||
|
{
|
||||||
|
@@ -10960,7 +11073,7 @@ save_gprs (rtx base, int offset, int first, int last)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (start > last)
|
||||||
|
- return insn;
|
||||||
|
+ goto emit;
|
||||||
|
|
||||||
|
addr = plus_constant (Pmode, base,
|
||||||
|
offset + (start - first) * UNITS_PER_LONG);
|
||||||
|
@@ -10978,7 +11091,7 @@ save_gprs (rtx base, int offset, int first, int last)
|
||||||
|
add_reg_note (insn, REG_FRAME_RELATED_EXPR, note);
|
||||||
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
|
||||||
|
- return insn;
|
||||||
|
+ goto emit;
|
||||||
|
}
|
||||||
|
|
||||||
|
note = gen_store_multiple (gen_rtx_MEM (Pmode, addr),
|
||||||
|
@@ -10997,9 +11110,15 @@ save_gprs (rtx base, int offset, int first, int last)
|
||||||
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return insn;
|
||||||
|
+ emit:
|
||||||
|
+ if (before != NULL_RTX)
|
||||||
|
+ out_insn = emit_insn_before (insn, before);
|
||||||
|
+ else
|
||||||
|
+ out_insn = emit_insn (insn);
|
||||||
|
+ INSN_ADDRESSES_NEW (out_insn, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
+
|
||||||
|
/* Generate insn to restore registers FIRST to LAST from
|
||||||
|
the register save area located at offset OFFSET
|
||||||
|
relative to register BASE. */
|
||||||
|
@@ -11423,12 +11542,12 @@ s390_emit_prologue (void)
|
||||||
|
/* Save call saved gprs. */
|
||||||
|
if (cfun_frame_layout.first_save_gpr != -1)
|
||||||
|
{
|
||||||
|
- insn = save_gprs (stack_pointer_rtx,
|
||||||
|
- cfun_frame_layout.gprs_offset +
|
||||||
|
- UNITS_PER_LONG * (cfun_frame_layout.first_save_gpr
|
||||||
|
- - cfun_frame_layout.first_save_gpr_slot),
|
||||||
|
- cfun_frame_layout.first_save_gpr,
|
||||||
|
- cfun_frame_layout.last_save_gpr);
|
||||||
|
+ save_gprs (stack_pointer_rtx,
|
||||||
|
+ cfun_frame_layout.gprs_offset +
|
||||||
|
+ UNITS_PER_LONG * (cfun_frame_layout.first_save_gpr
|
||||||
|
+ - cfun_frame_layout.first_save_gpr_slot),
|
||||||
|
+ cfun_frame_layout.first_save_gpr,
|
||||||
|
+ cfun_frame_layout.last_save_gpr);
|
||||||
|
|
||||||
|
/* This is not 100% correct. If we have more than one register saved,
|
||||||
|
then LAST_PROBE_OFFSET can move even closer to sp. */
|
||||||
|
@@ -11436,8 +11555,6 @@ s390_emit_prologue (void)
|
||||||
|
= (cfun_frame_layout.gprs_offset +
|
||||||
|
UNITS_PER_LONG * (cfun_frame_layout.first_save_gpr
|
||||||
|
- cfun_frame_layout.first_save_gpr_slot));
|
||||||
|
-
|
||||||
|
- emit_insn (insn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dummy insn to mark literal pool slot. */
|
||||||
|
@@ -11467,15 +11584,10 @@ s390_emit_prologue (void)
|
||||||
|
{
|
||||||
|
if (cfun_fpr_save_p (i))
|
||||||
|
{
|
||||||
|
- insn = save_fpr (stack_pointer_rtx, offset, i);
|
||||||
|
+ save_fpr (stack_pointer_rtx, offset, i);
|
||||||
|
if (offset < last_probe_offset)
|
||||||
|
last_probe_offset = offset;
|
||||||
|
offset += 8;
|
||||||
|
-
|
||||||
|
- /* If f4 and f6 are call clobbered they are saved due to
|
||||||
|
- stdargs and therefore are not frame related. */
|
||||||
|
- if (!call_used_regs[i])
|
||||||
|
- RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
}
|
||||||
|
else if (!TARGET_PACKED_STACK || call_used_regs[i])
|
||||||
|
offset += 8;
|
||||||
|
@@ -11491,11 +11603,10 @@ s390_emit_prologue (void)
|
||||||
|
for (i = FPR15_REGNUM; i >= FPR8_REGNUM && offset >= 0; i--)
|
||||||
|
if (cfun_fpr_save_p (i))
|
||||||
|
{
|
||||||
|
- insn = save_fpr (stack_pointer_rtx, offset, i);
|
||||||
|
+ save_fpr (stack_pointer_rtx, offset, i);
|
||||||
|
if (offset < last_probe_offset)
|
||||||
|
last_probe_offset = offset;
|
||||||
|
|
||||||
|
- RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
offset -= 8;
|
||||||
|
}
|
||||||
|
if (offset >= cfun_frame_layout.f8_offset)
|
||||||
|
@@ -11663,7 +11774,6 @@ s390_emit_prologue (void)
|
||||||
|
|
||||||
|
insn = save_fpr (temp_reg, offset, i);
|
||||||
|
offset += 8;
|
||||||
|
- RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
add_reg_note (insn, REG_FRAME_RELATED_EXPR,
|
||||||
|
gen_rtx_SET (gen_rtx_MEM (DFmode, addr),
|
||||||
|
gen_rtx_REG (DFmode, i)));
|
||||||
|
@@ -14158,15 +14268,11 @@ s390_optimize_prologue (void)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cfun_frame_layout.first_save_gpr != -1)
|
||||||
|
- {
|
||||||
|
- rtx s_pat = save_gprs (base,
|
||||||
|
- off + (cfun_frame_layout.first_save_gpr
|
||||||
|
- - first) * UNITS_PER_LONG,
|
||||||
|
- cfun_frame_layout.first_save_gpr,
|
||||||
|
- cfun_frame_layout.last_save_gpr);
|
||||||
|
- new_insn = emit_insn_before (s_pat, insn);
|
||||||
|
- INSN_ADDRESSES_NEW (new_insn, -1);
|
||||||
|
- }
|
||||||
|
+ save_gprs (base,
|
||||||
|
+ off + (cfun_frame_layout.first_save_gpr
|
||||||
|
+ - first) * UNITS_PER_LONG,
|
||||||
|
+ cfun_frame_layout.first_save_gpr,
|
||||||
|
+ cfun_frame_layout.last_save_gpr, insn);
|
||||||
|
|
||||||
|
remove_insn (insn);
|
||||||
|
continue;
|
||||||
|
diff --git a/gcc/config/s390/s390.opt b/gcc/config/s390/s390.opt
|
||||||
|
index 57d1b95bd65..344aa551f44 100644
|
||||||
|
--- a/gcc/config/s390/s390.opt
|
||||||
|
+++ b/gcc/config/s390/s390.opt
|
||||||
|
@@ -321,3 +321,7 @@ and the default behavior is to emit separate multiplication and addition
|
||||||
|
instructions for long doubles in vector registers, because measurements show
|
||||||
|
that this improves performance. This option allows overriding it for testing
|
||||||
|
purposes.
|
||||||
|
+
|
||||||
|
+mpreserve-args
|
||||||
|
+Target Var(s390_preserve_args_p) Init(0)
|
||||||
|
+Store all argument registers on the stack.
|
||||||
|
diff --git a/gcc/testsuite/gcc.target/s390/preserve-args-1.c b/gcc/testsuite/gcc.target/s390/preserve-args-1.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000000..24dcf547432
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/gcc/testsuite/gcc.target/s390/preserve-args-1.c
|
||||||
|
@@ -0,0 +1,17 @@
|
||||||
|
+/* Functional tests for the -mpreserve-args cmdline option. */
|
||||||
|
+
|
||||||
|
+/* { dg-do compile } */
|
||||||
|
+/* { dg-options "-O3 -march=z900 -mpreserve-args" } */
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+foo (int a, int b, int c, double d, double e)
|
||||||
|
+{
|
||||||
|
+ return a + c + (int)d + (int)e;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* { dg-final { scan-assembler "stmg\t%r2,%r4,\[0-9\]*\\(%r15\\)" { target lp64 } } } */
|
||||||
|
+/* { dg-final { scan-assembler "stm\t%r2,%r4,\[0-9\]*\\(%r15\\)" { target { ! lp64 } } } } */
|
||||||
|
+
|
||||||
|
+/* { dg-final { scan-assembler "std\t%f0,\[0-9\]*\\(%r15\\)" } } */
|
||||||
|
+/* { dg-final { scan-assembler "std\t%f2,\[0-9\]*\\(%r15\\)" } } */
|
||||||
|
diff --git a/gcc/testsuite/gcc.target/s390/preserve-args-2.c b/gcc/testsuite/gcc.target/s390/preserve-args-2.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000000..006aad9c371
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/gcc/testsuite/gcc.target/s390/preserve-args-2.c
|
||||||
|
@@ -0,0 +1,19 @@
|
||||||
|
+/* This test requires special handling of a GPR which is saved because
|
||||||
|
+ of -mpreserve-args but not restored. dwarf2cfi used to ICE for
|
||||||
|
+ this in maybe_record_trace_start. The solution was to introduce a
|
||||||
|
+ REG_CFA_NORESTORE reg note. */
|
||||||
|
+
|
||||||
|
+/* { dg-do compile } */
|
||||||
|
+/* { dg-options "-O2 -march=z900 -mpreserve-args" } */
|
||||||
|
+
|
||||||
|
+void *foo (void *);
|
||||||
|
+void bar ();
|
||||||
|
+int x;
|
||||||
|
+void *
|
||||||
|
+baz (void *y)
|
||||||
|
+{
|
||||||
|
+ if (__builtin_expect (x, 0))
|
||||||
|
+ return foo (y);
|
||||||
|
+ bar ();
|
||||||
|
+ return foo (y);
|
||||||
|
+}
|
||||||
|
diff --git a/gcc/testsuite/gcc.target/s390/preserve-args-3.c b/gcc/testsuite/gcc.target/s390/preserve-args-3.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000000..f4b135ab8e6
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/gcc/testsuite/gcc.target/s390/preserve-args-3.c
|
||||||
|
@@ -0,0 +1,19 @@
|
||||||
|
+/* Functional tests for the -mpreserve-args cmdline option. */
|
||||||
|
+
|
||||||
|
+/* { dg-do compile } */
|
||||||
|
+/* { dg-options "-O3 -march=z900 -mpreserve-args" } */
|
||||||
|
+
|
||||||
|
+#include <stdarg.h>
|
||||||
|
+int
|
||||||
|
+foo (int a, int, int c, double d, ...)
|
||||||
|
+{
|
||||||
|
+ va_list argp;
|
||||||
|
+ va_start(argp, d);
|
||||||
|
+ return a + c + va_arg(argp, int) + va_arg(argp, int) + (int)va_arg(argp, double);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* { dg-final { scan-assembler "stmg\t%r2,%r15,\[0-9\]*\\(%r15\\)" { target lp64 } } } */
|
||||||
|
+/* { dg-final { scan-assembler "stm\t%r2,%r15,\[0-9\]*\\(%r15\\)" { target { ! lp64 } } } } */
|
||||||
|
+
|
||||||
|
+/* { dg-final { scan-assembler "std\t%f0,\[0-9\]*\\(%r15\\)" } } */
|
||||||
|
+/* { dg-final { scan-assembler "std\t%f2,\[0-9\]*\\(%r15\\)" } } */
|
Loading…
Reference in new issue