Compare commits

...

No commits in common. "c8" and "imports/c8-beta/gcc-8.5.0-3.el8" have entirely different histories.

27 changed files with 9 additions and 6354 deletions

View File

@ -1,59 +0,0 @@
2024-04-18 Jakub Jelinek <jakub@redhat.com>
* tree-vect-stmts.c (vectorizable_call): For j == 0 use
vargs.safe_grow (nargs) rather than vargs.create (nargs), for j != 0
remove vargs.truncate (0). Instead of vargs.quick_push store into
vargs[i]. Use vargs[i] instead of gimple_call_arg (new_stmt, i)
if j != 0.
* gcc.c-torture/compile/20240418.c: New test.
--- gcc/tree-vect-stmts.c.jj 2021-04-22 15:48:48.228178359 +0200
+++ gcc/tree-vect-stmts.c 2024-04-18 13:21:46.104061529 +0200
@@ -3242,9 +3242,7 @@ vectorizable_call (gimple *gs, gimple_st
{
/* Build argument list for the vectorized call. */
if (j == 0)
- vargs.create (nargs);
- else
- vargs.truncate (0);
+ vargs.safe_grow (nargs);
if (slp_node)
{
@@ -3252,7 +3250,7 @@ vectorizable_call (gimple *gs, gimple_st
vec<tree> vec_oprnds0;
for (i = 0; i < nargs; i++)
- vargs.quick_push (gimple_call_arg (stmt, i));
+ vargs[i] = gimple_call_arg (stmt, i);
vect_get_slp_defs (vargs, slp_node, &vec_defs);
vec_oprnds0 = vec_defs[0];
@@ -3314,13 +3312,10 @@ vectorizable_call (gimple *gs, gimple_st
vec_oprnd0
= vect_get_vec_def_for_operand (op, stmt);
else
- {
- vec_oprnd0 = gimple_call_arg (new_stmt, i);
- vec_oprnd0
- = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
- }
+ vec_oprnd0
+ = vect_get_vec_def_for_stmt_copy (dt[i], vargs[i]);
- vargs.quick_push (vec_oprnd0);
+ vargs[i] = vec_oprnd0;
}
if (gimple_call_internal_p (stmt)
--- gcc/testsuite/gcc.c-torture/compile/20240418.c.jj 2024-04-18 13:24:10.180065661 +0200
+++ gcc/testsuite/gcc.c-torture/compile/20240418.c 2024-04-18 13:19:12.166194018 +0200
@@ -0,0 +1,7 @@
+void
+foo (signed char *p, unsigned long long *q)
+{
+ int i;
+ for (i = 0; i <= 64; i++)
+ *p++ = __builtin_popcountll (*q++);
+}

File diff suppressed because it is too large Load Diff

View File

@ -1,105 +0,0 @@
From 9c108bb84d3a2447dac730c455df658be0a2c751 Mon Sep 17 00:00:00 2001
From: Richard Sandiford <richard.sandiford@arm.com>
Date: Tue, 17 Aug 2021 15:15:27 +0100
Subject: [PATCH] aarch64: Add -mtune=neoverse-512tvb
To: gcc-patches@gcc.gnu.org
This patch adds an option to tune for Neoverse cores that have
a total vector bandwidth of 512 bits (4x128 for Advanced SIMD
and a vector-length-dependent equivalent for SVE). This is intended
to be a compromise between tuning aggressively for a single core like
Neoverse V1 (which can be too narrow) and tuning for AArch64 cores
in general (which can be too wide).
-mcpu=neoverse-512tvb is equivalent to -mcpu=neoverse-v1
-mtune=neoverse-512tvb.
gcc/
* doc/invoke.texi: Document -mtune=neoverse-512tvb and
-mcpu=neoverse-512tvb.
* config/aarch64/aarch64-cores.def (neoverse-512tvb): New entry.
* config/aarch64/aarch64-tune.md: Regenerate.
(cherry picked from commit 048039c49b96875144f67e7789fdea54abf7710b)
---
gcc/config/aarch64/aarch64-cores.def | 1 +
gcc/config/aarch64/aarch64-tune.md | 2 +-
gcc/doc/invoke.texi | 25 ++++++++++++++++++++++---
3 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
index dfb839c01cc..f348d31e22e 100644
--- a/gcc/config/aarch64/aarch64-cores.def
+++ b/gcc/config/aarch64/aarch64-cores.def
@@ -99,6 +99,7 @@ AARCH64_CORE("saphira", saphira, falkor, 8_3A, AARCH64_FL_FOR_ARCH8_3
/* ARM ('A') cores. */
AARCH64_CORE("zeus", zeus, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_SVE | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_SVE | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
+AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_SVE | AARCH64_FL_RNG, neoversev1, INVALID_IMP, INVALID_CORE, -1)
/* Armv8.5-A Architecture Processors. */
AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_F16 | AARCH64_FL_SVE | AARCH64_FL_RNG, neoversen2, 0x41, 0xd49, -1)
diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md
index 2d7c9aa4740..09b76480f0b 100644
--- a/gcc/config/aarch64/aarch64-tune.md
+++ b/gcc/config/aarch64/aarch64-tune.md
@@ -1,5 +1,5 @@
;; -*- buffer-read-only: t -*-
;; Generated automatically by gentune.sh from aarch64-cores.def
(define_attr "tune"
- "cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,thunderxt81,thunderxt83,xgene1,falkor,qdf24xx,exynosm1,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,ares,neoversen1,saphira,zeus,neoversev1,neoversen2,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55"
+ "cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,thunderxt81,thunderxt83,xgene1,falkor,qdf24xx,exynosm1,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,ares,neoversen1,saphira,zeus,neoversev1,neoverse512tvb,neoversen2,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55"
(const (symbol_ref "((enum attr_tune) aarch64_tune)")))
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 78ca7738df2..68fda03281a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -14772,9 +14772,9 @@ performance of the code. Permissible values for this option are:
@samp{generic}, @samp{cortex-a35}, @samp{cortex-a53}, @samp{cortex-a55},
@samp{cortex-a57}, @samp{cortex-a72}, @samp{cortex-a73}, @samp{cortex-a75},
@samp{cortex-a76}, @samp{ares}, @samp{neoverse-n1}, @samp{neoverse-n2},
-@samp{neoverse-v1}, @samp{zeus}, @samp{exynos-m1}, @samp{falkor},
-@samp{qdf24xx}, @samp{saphira}, @samp{xgene1}, @samp{vulcan}, @samp{thunderx},
-@samp{thunderxt88}, @samp{thunderxt88p1}, @samp{thunderxt81},
+@samp{neoverse-v1}, @samp{zeus}, @samp{neoverse-512tvb}, @samp{exynos-m1},
+@samp{falkor}, @samp{qdf24xx}, @samp{saphira}, @samp{xgene1}, @samp{vulcan},
+@samp{thunderx}, @samp{thunderxt88}, @samp{thunderxt88p1}, @samp{thunderxt81},
@samp{thunderxt83}, @samp{thunderx2t99}, @samp{cortex-a57.cortex-a53},
@samp{cortex-a72.cortex-a53}, @samp{cortex-a73.cortex-a35},
@samp{cortex-a73.cortex-a53}, @samp{cortex-a75.cortex-a55},
@@ -14785,6 +14785,15 @@ The values @samp{cortex-a57.cortex-a53}, @samp{cortex-a72.cortex-a53},
@samp{cortex-a75.cortex-a55} specify that GCC should tune for a
big.LITTLE system.
+The value @samp{neoverse-512tvb} specifies that GCC should tune
+for Neoverse cores that (a) implement SVE and (b) have a total vector
+bandwidth of 512 bits per cycle. In other words, the option tells GCC to
+tune for Neoverse cores that can execute 4 128-bit Advanced SIMD arithmetic
+instructions a cycle and that can execute an equivalent number of SVE
+arithmetic instructions per cycle (2 for 256-bit SVE, 4 for 128-bit SVE).
+This is more general than tuning for a specific core like Neoverse V1
+but is more specific than the default tuning described below.
+
Additionally on native AArch64 GNU/Linux systems the value
@samp{native} tunes performance to the host system. This option has no effect
if the compiler is unable to recognize the processor of the host system.
@@ -14814,6 +14823,16 @@ by @option{-mtune}). Where this option is used in conjunction
with @option{-march} or @option{-mtune}, those options take precedence
over the appropriate part of this option.
+@option{-mcpu=neoverse-512tvb} is special in that it does not refer
+to a specific core, but instead refers to all Neoverse cores that
+(a) implement SVE and (b) have a total vector bandwidth of 512 bits
+a cycle. Unless overridden by @option{-march},
+@option{-mcpu=neoverse-512tvb} generates code that can run on a
+Neoverse V1 core, since Neoverse V1 is the first Neoverse core with
+these properties. Unless overridden by @option{-mtune},
+@option{-mcpu=neoverse-512tvb} tunes code in the same way as for
+@option{-mtune=neoverse-512tvb}.
+
@item -moverride=@var{string}
@opindex moverride
Override tuning decisions made by the back-end in response to a
--
2.25.1

View File

@ -1,294 +0,0 @@
From 88bf1c3910e4cf97dcb85c6d32291c23e572a516 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 27 Oct 2021 07:48:54 -0700
Subject: [PATCH 1/4] x86: Add -mharden-sls=[none|all|return|indirect-branch]
Add -mharden-sls= to mitigate against straight line speculation (SLS)
for function return and indirect branch by adding an INT3 instruction
after function return and indirect branch.
gcc/
PR target/102952
* config/i386/i386-opts.h (harden_sls): New enum.
* config/i386/i386.c (output_indirect_thunk): Mitigate against
SLS for function return.
(ix86_output_function_return): Likewise.
(ix86_output_jmp_thunk_or_indirect): Mitigate against indirect
branch.
(ix86_output_indirect_jmp): Likewise.
(ix86_output_call_insn): Likewise.
* config/i386/i386.opt: Add -mharden-sls=.
* doc/invoke.texi: Document -mharden-sls=.
gcc/testsuite/
PR target/102952
* gcc.target/i386/harden-sls-1.c: New test.
* gcc.target/i386/harden-sls-2.c: Likewise.
* gcc.target/i386/harden-sls-3.c: Likewise.
* gcc.target/i386/harden-sls-4.c: Likewise.
* gcc.target/i386/harden-sls-5.c: Likewise.
(cherry picked from commit 53a643f8568067d7700a9f2facc8ba39974973d3)
---
gcc/config/i386/i386-opts.h | 7 +++++++
gcc/config/i386/i386.c | 22 +++++++++++++++-----
gcc/config/i386/i386.opt | 20 ++++++++++++++++++
gcc/doc/invoke.texi | 10 ++++++++-
gcc/testsuite/gcc.target/i386/harden-sls-1.c | 14 +++++++++++++
gcc/testsuite/gcc.target/i386/harden-sls-2.c | 14 +++++++++++++
gcc/testsuite/gcc.target/i386/harden-sls-3.c | 14 +++++++++++++
gcc/testsuite/gcc.target/i386/harden-sls-4.c | 16 ++++++++++++++
gcc/testsuite/gcc.target/i386/harden-sls-5.c | 17 +++++++++++++++
9 files changed, 128 insertions(+), 6 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-1.c
create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-2.c
create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-3.c
create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-4.c
create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-5.c
diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
index 46366cbfa72..34718b6d52c 100644
--- a/gcc/config/i386/i386-opts.h
+++ b/gcc/config/i386/i386-opts.h
@@ -119,4 +119,11 @@ enum indirect_branch {
indirect_branch_thunk_extern
};
+enum harden_sls {
+ harden_sls_none = 0,
+ harden_sls_return = 1 << 0,
+ harden_sls_indirect_branch = 1 << 1,
+ harden_sls_all = harden_sls_return | harden_sls_indirect_branch
+};
+
#endif
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 31502774ef3..eb9303f8742 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -10977,6 +10977,9 @@ output_indirect_thunk (enum indirect_thunk_prefix need_prefix,
fputs ("\tbnd ret\n", asm_out_file);
else
fputs ("\tret\n", asm_out_file);
+
+ if ((ix86_harden_sls & harden_sls_return))
+ fputs ("\tint3\n", asm_out_file);
}
/* Output a funtion with a call and return thunk for indirect branch.
@@ -28728,6 +28731,8 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name,
fprintf (asm_out_file, "\tjmp\t");
assemble_name (asm_out_file, thunk_name);
putc ('\n', asm_out_file);
+ if ((ix86_harden_sls & harden_sls_indirect_branch))
+ fputs ("\tint3\n", asm_out_file);
}
else
output_indirect_thunk (need_prefix, regno);
@@ -28973,10 +28978,10 @@ ix86_output_indirect_jmp (rtx call_op)
gcc_unreachable ();
ix86_output_indirect_branch (call_op, "%0", true);
- return "";
}
else
- return "%!jmp\t%A0";
+ output_asm_insn ("%!jmp\t%A0", &call_op);
+ return (ix86_harden_sls & harden_sls_indirect_branch) ? "int3" : "";
}
/* Output function return. CALL_OP is the jump target. Add a REP
@@ -29018,9 +29023,11 @@ ix86_output_function_return (bool long_p)
}
if (!long_p || ix86_bnd_prefixed_insn_p (current_output_insn))
- return "%!ret";
+ output_asm_insn ("%!ret", NULL);
+ else
+ output_asm_insn ("rep%; ret", NULL);
- return "rep%; ret";
+ return (ix86_harden_sls & harden_sls_return) ? "int3" : "";
}
/* Output indirect function return. RET_OP is the function return
@@ -29158,7 +29165,12 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
if (output_indirect_p && !direct_p)
ix86_output_indirect_branch (call_op, xasm, true);
else
- output_asm_insn (xasm, &call_op);
+ {
+ output_asm_insn (xasm, &call_op);
+ if (!direct_p
+ && (ix86_harden_sls & harden_sls_indirect_branch))
+ return "int3";
+ }
return "";
}
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index d9bd909a885..3ae48609e25 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -1055,3 +1055,23 @@ Support MOVDIRI built-in functions and code generation.
mmovdir64b
Target Report Mask(ISA_MOVDIR64B) Var(ix86_isa_flags2) Save
Support MOVDIR64B built-in functions and code generation.
+
+mharden-sls=
+Target RejectNegative Joined Enum(harden_sls) Var(ix86_harden_sls) Init(harden_sls_none)
+Generate code to mitigate against straight line speculation.
+
+Enum
+Name(harden_sls) Type(enum harden_sls)
+Known choices for mitigation against straight line speculation with -mharden-sls=:
+
+EnumValue
+Enum(harden_sls) String(none) Value(harden_sls_none)
+
+EnumValue
+Enum(harden_sls) String(return) Value(harden_sls_return)
+
+EnumValue
+Enum(harden_sls) String(indirect-branch) Value(harden_sls_indirect_branch)
+
+EnumValue
+Enum(harden_sls) String(all) Value(harden_sls_all)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 78ca7738df2..1e20efd6969 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1284,7 +1284,7 @@ See RS/6000 and PowerPC Options.
-mstack-protector-guard-symbol=@var{symbol} -mmitigate-rop @gol
-mgeneral-regs-only -mcall-ms2sysv-xlogues @gol
-mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol
--mindirect-branch-register}
+-mindirect-branch-register -mharden-sls=@var{choice}}
@emph{x86 Windows Options}
@gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
@@ -28036,6 +28036,14 @@ not be reachable in the large code model.
@opindex -mindirect-branch-register
Force indirect call and jump via register.
+@item -mharden-sls=@var{choice}
+@opindex mharden-sls
+Generate code to mitigate against straight line speculation (SLS) with
+@var{choice}. The default is @samp{none} which disables all SLS
+hardening. @samp{return} enables SLS hardening for function return.
+@samp{indirect-branch} enables SLS hardening for indirect branch.
+@samp{all} enables all SLS hardening.
+
@end table
These @samp{-m} switches are supported in addition to the above
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-1.c b/gcc/testsuite/gcc.target/i386/harden-sls-1.c
new file mode 100644
index 00000000000..6f70dc94a23
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mharden-sls=all" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+extern void foo (void);
+
+void
+bar (void)
+{
+ foo ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]+_?foo" } } */
+/* { dg-final { scan-assembler-not {int3} } } */
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-2.c b/gcc/testsuite/gcc.target/i386/harden-sls-2.c
new file mode 100644
index 00000000000..a7c59078d03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mharden-sls=all" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+extern void (*fptr) (void);
+
+void
+foo (void)
+{
+ fptr ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]+_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-times "int3" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-3.c b/gcc/testsuite/gcc.target/i386/harden-sls-3.c
new file mode 100644
index 00000000000..1a6056b6d7b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-3.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=thunk -mharden-sls=all" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+extern void (*fptr) (void);
+
+void
+foo (void)
+{
+ fptr ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]+_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-times "int3" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-4.c b/gcc/testsuite/gcc.target/i386/harden-sls-4.c
new file mode 100644
index 00000000000..f70dd1379d3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-4.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=keep -mharden-sls=all" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+extern void (*fptr) (void);
+
+void
+foo (void)
+{
+ fptr ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]+\\*_?fptr" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+fptr\\(%rip\\), %eax" { target x32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]+\\*%rax" { target x32 } } } */
+/* { dg-final { scan-assembler-times "int3" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-5.c b/gcc/testsuite/gcc.target/i386/harden-sls-5.c
new file mode 100644
index 00000000000..613c44c6f82
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-5.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -mharden-sls=return" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "ret" 1 } } */
+/* { dg-final { scan-assembler-times "int3" 1 } } */
--
2.36.1

View File

@ -1,155 +0,0 @@
From 0df8313a0a5d8533f2487e21d7b42e9adee28f18 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 27 Oct 2021 06:27:15 -0700
Subject: [PATCH 2/4] x86: Add -mindirect-branch-cs-prefix
Add -mindirect-branch-cs-prefix to add CS prefix to call and jmp to
indirect thunk with branch target in r8-r15 registers so that the call
and jmp instruction length is 6 bytes to allow them to be replaced with
"lfence; call *%r8-r15" or "lfence; jmp *%r8-r15" at run-time.
gcc/
PR target/102952
* config/i386/i386.c (ix86_output_jmp_thunk_or_indirect): Emit
CS prefix for -mindirect-branch-cs-prefix.
(ix86_output_indirect_branch_via_reg): Likewise.
* config/i386/i386.opt: Add -mindirect-branch-cs-prefix.
* doc/invoke.texi: Document -mindirect-branch-cs-prefix.
gcc/testsuite/
PR target/102952
* gcc.target/i386/indirect-thunk-cs-prefix-1.c: New test.
* gcc.target/i386/indirect-thunk-cs-prefix-2.c: Likewise.
(cherry picked from commit 2196a681d7810ad8b227bf983f38ba716620545e)
---
gcc/config/i386/i386.c | 14 ++++++++++++--
gcc/config/i386/i386.opt | 4 ++++
gcc/doc/invoke.texi | 10 +++++++++-
.../gcc.target/i386/indirect-thunk-cs-prefix-1.c | 14 ++++++++++++++
.../gcc.target/i386/indirect-thunk-cs-prefix-2.c | 15 +++++++++++++++
5 files changed, 54 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c
create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index eb9303f8742..8442dd0daea 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -28728,7 +28728,12 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name,
if (need_prefix == indirect_thunk_prefix_bnd)
fprintf (asm_out_file, "\tbnd jmp\t");
else
- fprintf (asm_out_file, "\tjmp\t");
+ {
+ if (REX_INT_REGNO_P (regno)
+ && ix86_indirect_branch_cs_prefix)
+ fprintf (asm_out_file, "\tcs\n");
+ fprintf (asm_out_file, "\tjmp\t");
+ }
assemble_name (asm_out_file, thunk_name);
putc ('\n', asm_out_file);
if ((ix86_harden_sls & harden_sls_indirect_branch))
@@ -28787,7 +28792,12 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
if (need_prefix == indirect_thunk_prefix_bnd)
fprintf (asm_out_file, "\tbnd call\t");
else
- fprintf (asm_out_file, "\tcall\t");
+ {
+ if (REX_INT_REGNO_P (regno)
+ && ix86_indirect_branch_cs_prefix)
+ fprintf (asm_out_file, "\tcs\n");
+ fprintf (asm_out_file, "\tcall\t");
+ }
assemble_name (asm_out_file, thunk_name);
putc ('\n', asm_out_file);
return;
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 3ae48609e25..9f67ef558dc 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -1044,6 +1044,10 @@ Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
EnumValue
Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
+mindirect-branch-cs-prefix
+Target Var(ix86_indirect_branch_cs_prefix) Init(0)
+Add CS prefix to call and jmp to indirect thunk with branch target in r8-r15 registers.
+
mindirect-branch-register
Target Report Var(ix86_indirect_branch_register) Init(0)
Force indirect call and jump via register.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 1e20efd6969..605cd4b93f1 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1284,7 +1284,8 @@ See RS/6000 and PowerPC Options.
-mstack-protector-guard-symbol=@var{symbol} -mmitigate-rop @gol
-mgeneral-regs-only -mcall-ms2sysv-xlogues @gol
-mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol
--mindirect-branch-register -mharden-sls=@var{choice}}
+-mindirect-branch-register -mharden-sls=@var{choice} @gol
+-mindirect-branch-cs-prefix}
@emph{x86 Windows Options}
@gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
@@ -28044,6 +28045,13 @@ hardening. @samp{return} enables SLS hardening for function return.
@samp{indirect-branch} enables SLS hardening for indirect branch.
@samp{all} enables all SLS hardening.
+@item -mindirect-branch-cs-prefix
+@opindex mindirect-branch-cs-prefix
+Add CS prefix to call and jmp to indirect thunk with branch target in
+r8-r15 registers so that the call and jmp instruction length is 6 bytes
+to allow them to be replaced with @samp{lfence; call *%r8-r15} or
+@samp{lfence; jmp *%r8-r15} at run-time.
+
@end table
These @samp{-m} switches are supported in addition to the above
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c
new file mode 100644
index 00000000000..db2f3416823
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -ffixed-rax -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rdi -ffixed-rsi -mindirect-branch-cs-prefix -mindirect-branch=thunk-extern" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+extern void (*fptr) (void);
+
+void
+foo (void)
+{
+ fptr ();
+}
+
+/* { dg-final { scan-assembler-times "jmp\[ \t\]+_?__x86_indirect_thunk_r\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "\tcs" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c
new file mode 100644
index 00000000000..adfc39a49d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -ffixed-rax -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rdi -ffixed-rsi -mindirect-branch-cs-prefix -mindirect-branch=thunk-extern" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+extern void (*bar) (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "call\[ \t\]+_?__x86_indirect_thunk_r\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "\tcs" 1 } } */
--
2.36.1

View File

@ -1,108 +0,0 @@
From 621de498ee19e1f2642eebde707430254c0459c0 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 5 Jan 2022 16:33:16 -0800
Subject: [PATCH 3/4] x86: Rename -harden-sls=indirect-branch to
-harden-sls=indirect-jmp
Indirect branch also includes indirect call instructions. Rename
-harden-sls=indirect-branch to -harden-sls=indirect-jmp to match its
intended behavior.
PR target/102952
* config/i386/i386-opts.h (harden_sls): Replace
harden_sls_indirect_branch with harden_sls_indirect_jmp.
* config/i386/i386.c (ix86_output_jmp_thunk_or_indirect):
Likewise.
(ix86_output_indirect_jmp): Likewise.
(ix86_output_call_insn): Likewise.
* config/i386/i386.opt: Replace indirect-branch with
indirect-jmp. Replace harden_sls_indirect_branch with
harden_sls_indirect_jmp.
* doc/invoke.texi (-harden-sls=): Replace indirect-branch with
indirect-jmp.
(cherry picked from commit ed8060950c64f2e449aaf90e438aa26d0d9d0b31)
---
gcc/config/i386/i386-opts.h | 4 ++--
gcc/config/i386/i386.c | 6 +++---
gcc/config/i386/i386.opt | 2 +-
gcc/doc/invoke.texi | 4 ++--
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
index 34718b6d52c..47facc254cd 100644
--- a/gcc/config/i386/i386-opts.h
+++ b/gcc/config/i386/i386-opts.h
@@ -122,8 +122,8 @@ enum indirect_branch {
enum harden_sls {
harden_sls_none = 0,
harden_sls_return = 1 << 0,
- harden_sls_indirect_branch = 1 << 1,
- harden_sls_all = harden_sls_return | harden_sls_indirect_branch
+ harden_sls_indirect_jmp = 1 << 1,
+ harden_sls_all = harden_sls_return | harden_sls_indirect_jmp
};
#endif
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 8442dd0daea..3bc14e20105 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -28736,7 +28736,7 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name,
}
assemble_name (asm_out_file, thunk_name);
putc ('\n', asm_out_file);
- if ((ix86_harden_sls & harden_sls_indirect_branch))
+ if ((ix86_harden_sls & harden_sls_indirect_jmp))
fputs ("\tint3\n", asm_out_file);
}
else
@@ -28991,7 +28991,7 @@ ix86_output_indirect_jmp (rtx call_op)
}
else
output_asm_insn ("%!jmp\t%A0", &call_op);
- return (ix86_harden_sls & harden_sls_indirect_branch) ? "int3" : "";
+ return (ix86_harden_sls & harden_sls_indirect_jmp) ? "int3" : "";
}
/* Output function return. CALL_OP is the jump target. Add a REP
@@ -29178,7 +29178,7 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
{
output_asm_insn (xasm, &call_op);
if (!direct_p
- && (ix86_harden_sls & harden_sls_indirect_branch))
+ && (ix86_harden_sls & harden_sls_indirect_jmp))
return "int3";
}
return "";
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 9f67ef558dc..7a5c7b9369a 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -1075,7 +1075,7 @@ EnumValue
Enum(harden_sls) String(return) Value(harden_sls_return)
EnumValue
-Enum(harden_sls) String(indirect-branch) Value(harden_sls_indirect_branch)
+Enum(harden_sls) String(indirect-jmp) Value(harden_sls_indirect_jmp)
EnumValue
Enum(harden_sls) String(all) Value(harden_sls_all)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 605cd4b93f1..20d8e3fd782 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -28041,8 +28041,8 @@ Force indirect call and jump via register.
@opindex mharden-sls
Generate code to mitigate against straight line speculation (SLS) with
@var{choice}. The default is @samp{none} which disables all SLS
-hardening. @samp{return} enables SLS hardening for function return.
-@samp{indirect-branch} enables SLS hardening for indirect branch.
+hardening. @samp{return} enables SLS hardening for function returns.
+@samp{indirect-jmp} enables SLS hardening for indirect jumps.
@samp{all} enables all SLS hardening.
@item -mindirect-branch-cs-prefix
--
2.36.1

View File

@ -1,75 +0,0 @@
From 5a5e7890cefa112e95e1de9800d8081c2a38a1da Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 5 Jan 2022 18:04:21 -0800
Subject: [PATCH 4/4] x86: Generate INT3 for __builtin_eh_return
Generate INT3 after indirect jmp in exception return for -fcf-protection
with -mharden-sls=indirect-jmp.
gcc/
PR target/103925
* config/i386/i386.c (ix86_output_indirect_function_return):
Generate INT3 after indirect jmp for -mharden-sls=indirect-jmp.
gcc/testsuite/
PR target/103925
* gcc.target/i386/harden-sls-6.c: New test.
(cherry picked from commit c2e5c4feed32c808591b5278f680bbabe63eb225)
---
gcc/config/i386/i386.c | 9 ++++++---
gcc/testsuite/gcc.target/i386/harden-sls-6.c | 18 ++++++++++++++++++
2 files changed, 24 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-6.c
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 3bc14e20105..dbc3d462fda 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -29083,11 +29083,14 @@ ix86_output_indirect_function_return (rtx ret_op)
}
else
output_indirect_thunk (need_prefix, regno);
-
- return "";
}
else
- return "%!jmp\t%A0";
+ {
+ output_asm_insn ("%!jmp\t%A0", &ret_op);
+ if (ix86_harden_sls & harden_sls_indirect_jmp)
+ fputs ("\tint3\n", asm_out_file);
+ }
+ return "";
}
/* Split simple return with popping POPC bytes from stack to indirect
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-6.c b/gcc/testsuite/gcc.target/i386/harden-sls-6.c
new file mode 100644
index 00000000000..9068eb64008
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-6.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fcf-protection -mharden-sls=indirect-jmp" } */
+
+struct _Unwind_Context _Unwind_Resume_or_Rethrow_this_context;
+
+void offset (int);
+
+struct _Unwind_Context {
+ void *reg[7];
+} _Unwind_Resume_or_Rethrow() {
+ struct _Unwind_Context cur_contextcur_context =
+ _Unwind_Resume_or_Rethrow_this_context;
+ offset(0);
+ __builtin_eh_return ((long) offset, 0);
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]+\\*%rcx" } } */
+/* { dg-final { scan-assembler-times "int3" 1 } } */
--
2.36.1

View File

@ -1,516 +0,0 @@
diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c
index d93dcfa..f47565c 100644
--- a/gcc/fortran/io.c
+++ b/gcc/fortran/io.c
@@ -909,6 +909,13 @@ data_desc:
if (u != FMT_POSINT)
{
+ if (flag_dec)
+ {
+ /* Assume a default width based on the variable size. */
+ saved_token = u;
+ break;
+ }
+
format_locus.nextc += format_string_pos;
gfc_error ("Positive width required in format "
"specifier %s at %L", token_to_string (t),
@@ -1030,6 +1037,13 @@ data_desc:
goto fail;
if (t != FMT_ZERO && t != FMT_POSINT)
{
+ if (flag_dec)
+ {
+ /* Assume the default width is expected here and continue lexing. */
+ value = 0; /* It doesn't matter what we set the value to here. */
+ saved_token = t;
+ break;
+ }
error = nonneg_required;
goto syntax;
}
@@ -1099,8 +1113,17 @@ data_desc:
goto fail;
if (t != FMT_ZERO && t != FMT_POSINT)
{
- error = nonneg_required;
- goto syntax;
+ if (flag_dec)
+ {
+ /* Assume the default width is expected here and continue lexing. */
+ value = 0; /* It doesn't matter what we set the value to here. */
+ saved_token = t;
+ }
+ else
+ {
+ error = nonneg_required;
+ goto syntax;
+ }
}
else if (is_input && t == FMT_ZERO)
{
diff --git a/gcc/testsuite/gfortran.dg/fmt_f_default_field_width.f90 b/gcc/testsuite/gfortran.dg/fmt_f_default_field_width.f90
new file mode 100644
index 0000000..b087b8f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_f_default_field_width.f90
@@ -0,0 +1,43 @@
+! { dg-do run }
+! { dg-options -fdec }
+!
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
+!
+! This feature is not part of any Fortran standard, but it is supported by the
+! Oracle Fortran compiler and others.
+!
+! libgfortran uses printf() internally to implement FORMAT. If you print float
+! values to a higher precision than the type can actually store, the results
+! are implementation dependent: some platforms print zeros, others print random
+! numbers. Don't depend on this behaviour in tests because they will not be
+! portable.
+
+ character(50) :: buffer
+
+ real*4 :: real_4
+ real*8 :: real_8
+ real*16 :: real_16
+ integer :: len
+
+ real_4 = 4.18
+ write(buffer, '(A, F, A)') ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 4.1799998:") call abort
+
+ real_4 = 0.00000018
+ write(buffer, '(A, F, A)') ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 0.0000002:") call abort
+
+ real_8 = 4.18
+ write(buffer, '(A, F, A)') ':',real_8,':'
+ print *,buffer
+ len = len_trim(buffer)
+ if (len /= 27) call abort
+
+ real_16 = 4.18
+ write(buffer, '(A, F, A)') ':',real_16,':'
+ print *,buffer
+ len = len_trim(buffer)
+ if (len /= 44) call abort
+end
diff --git a/gcc/testsuite/gfortran.dg/fmt_g_default_field_width.f90 b/gcc/testsuite/gfortran.dg/fmt_g_default_field_width.f90
new file mode 100644
index 0000000..3d3a476
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_g_default_field_width.f90
@@ -0,0 +1,48 @@
+! { dg-do run }
+! { dg-options -fdec }
+!
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
+!
+! This feature is not part of any Fortran standard, but it is supported by the
+! Oracle Fortran compiler and others.
+!
+! libgfortran uses printf() internally to implement FORMAT. If you print float
+! values to a higher precision than the type can actually store, the results
+! are implementation dependent: some platforms print zeros, others print random
+! numbers. Don't depend on this behaviour in tests because they will not be
+! portable.
+
+ character(50) :: buffer
+
+ real*4 :: real_4
+ real*8 :: real_8
+ real*16 :: real_16
+ integer :: len
+
+ real_4 = 4.18
+ write(buffer, '(A, G, A)') ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 4.180000 :") call abort
+
+ real_4 = 0.00000018
+ write(buffer, '(A, G, A)') ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 0.1800000E-06:") call abort
+
+ real_4 = 18000000.4
+ write(buffer, '(A, G, A)') ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 0.1800000E+08:") call abort
+
+ real_8 = 4.18
+ write(buffer, '(A, G, A)') ':',real_8,':'
+ print *,buffer
+ len = len_trim(buffer)
+ if (len /= 27) call abort
+
+ real_16 = 4.18
+ write(buffer, '(A, G, A)') ':',real_16,':'
+ print *,buffer
+ len = len_trim(buffer)
+ if (len /= 44) call abort
+end
diff --git a/gcc/testsuite/gfortran.dg/fmt_i_default_field_width.f90 b/gcc/testsuite/gfortran.dg/fmt_i_default_field_width.f90
new file mode 100644
index 0000000..ac4e165
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_i_default_field_width.f90
@@ -0,0 +1,38 @@
+! { dg-do run }
+! { dg-options -fdec }
+!
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
+!
+! This feature is not part of any Fortran standard, but it is supported by the
+! Oracle Fortran compiler and others.
+
+ character(50) :: buffer
+ character(1) :: colon
+
+ integer*2 :: integer_2
+ integer*4 :: integer_4
+ integer*8 :: integer_8
+
+ write(buffer, '(A, I, A)') ':',12340,':'
+ print *,buffer
+ if (buffer.ne.": 12340:") call abort
+
+ read(buffer, '(A1, I, A1)') colon, integer_4, colon
+ if (integer_4.ne.12340) call abort
+
+ integer_2 = -99
+ write(buffer, '(A, I, A)') ':',integer_2,':'
+ print *,buffer
+ if (buffer.ne.": -99:") call abort
+
+ integer_8 = -11112222
+ write(buffer, '(A, I, A)') ':',integer_8,':'
+ print *,buffer
+ if (buffer.ne.": -11112222:") call abort
+
+! If the width is 7 and there are 7 leading zeroes, the result should be zero.
+ integer_2 = 789
+ buffer = '0000000789'
+ read(buffer, '(I)') integer_2
+ if (integer_2.ne.0) call abort
+end
diff --git a/libgfortran/io/format.c b/libgfortran/io/format.c
index c2abdd7..692b1ff 100644
--- a/libgfortran/io/format.c
+++ b/libgfortran/io/format.c
@@ -956,12 +956,33 @@ parse_format_list (st_parameter_dt *dtp, bool *seen_dd)
*seen_dd = true;
if (u != FMT_POSINT && u != FMT_ZERO)
{
+ if (dtp->common.flags & IOPARM_DT_DEC_EXT)
+ {
+ tail->u.real.w = DEFAULT_WIDTH;
+ tail->u.real.d = 0;
+ tail->u.real.e = -1;
+ fmt->saved_token = u;
+ break;
+ }
fmt->error = nonneg_required;
goto finished;
}
}
+ else if (u == FMT_ZERO)
+ {
+ fmt->error = posint_required;
+ goto finished;
+ }
else if (u != FMT_POSINT)
{
+ if (dtp->common.flags & IOPARM_DT_DEC_EXT)
+ {
+ tail->u.real.w = DEFAULT_WIDTH;
+ tail->u.real.d = 0;
+ tail->u.real.e = -1;
+ fmt->saved_token = u;
+ break;
+ }
fmt->error = posint_required;
goto finished;
}
@@ -1099,6 +1120,13 @@ parse_format_list (st_parameter_dt *dtp, bool *seen_dd)
{
if (t != FMT_POSINT)
{
+ if (dtp->common.flags & IOPARM_DT_DEC_EXT)
+ {
+ tail->u.integer.w = DEFAULT_WIDTH;
+ tail->u.integer.m = -1;
+ fmt->saved_token = t;
+ break;
+ }
fmt->error = posint_required;
goto finished;
}
@@ -1107,6 +1135,13 @@ parse_format_list (st_parameter_dt *dtp, bool *seen_dd)
{
if (t != FMT_ZERO && t != FMT_POSINT)
{
+ if (dtp->common.flags & IOPARM_DT_DEC_EXT)
+ {
+ tail->u.integer.w = DEFAULT_WIDTH;
+ tail->u.integer.m = -1;
+ fmt->saved_token = t;
+ break;
+ }
fmt->error = nonneg_required;
goto finished;
}
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index 5583183..d1d08e8 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -981,5 +981,55 @@ memset4 (gfc_char4_t *p, gfc_char4_t c, int k)
*p++ = c;
}
+/* Used in width fields to indicate that the default should be used */
+#define DEFAULT_WIDTH -1
+
+/* Defaults for certain format field descriptors. These are decided based on
+ * the type of the value being formatted.
+ *
+ * The behaviour here is modelled on the Oracle Fortran compiler. At the time
+ * of writing, the details were available at this URL:
+ *
+ * https://docs.oracle.com/cd/E19957-01/805-4939/6j4m0vnc3/index.html#z4000743746d
+ */
+
+static inline int
+default_width_for_integer (int kind)
+{
+ switch (kind)
+ {
+ case 1:
+ case 2: return 7;
+ case 4: return 12;
+ case 8: return 23;
+ case 16: return 44;
+ default: return 0;
+ }
+}
+
+static inline int
+default_width_for_float (int kind)
+{
+ switch (kind)
+ {
+ case 4: return 15;
+ case 8: return 25;
+ case 16: return 42;
+ default: return 0;
+ }
+}
+
+static inline int
+default_precision_for_float (int kind)
+{
+ switch (kind)
+ {
+ case 4: return 7;
+ case 8: return 16;
+ case 16: return 33;
+ default: return 0;
+ }
+}
+
#endif
diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c
index 2c9de48..e911e35 100644
--- a/libgfortran/io/read.c
+++ b/libgfortran/io/read.c
@@ -629,6 +629,12 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
w = f->u.w;
+ /* This is a legacy extension, and the frontend will only allow such cases
+ * through when -fdec-format-defaults is passed.
+ */
+ if (w == DEFAULT_WIDTH)
+ w = default_width_for_integer (length);
+
p = read_block_form (dtp, &w);
if (p == NULL)
diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c
index a7307a8..c8e52fb 100644
--- a/libgfortran/io/write.c
+++ b/libgfortran/io/write.c
@@ -684,9 +684,8 @@ write_l (st_parameter_dt *dtp, const fnode *f, char *source, int len)
p[wlen - 1] = (n) ? 'T' : 'F';
}
-
static void
-write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n)
+write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n, int len)
{
int w, m, digits, nzero, nblank;
char *p;
@@ -719,6 +718,9 @@ write_boz (st_parameter_dt *dtp, const fnode *f, const char *q, int n)
/* Select a width if none was specified. The idea here is to always
print something. */
+ if (w == DEFAULT_WIDTH)
+ w = default_width_for_integer (len);
+
if (w == 0)
w = ((digits < m) ? m : digits);
@@ -845,6 +847,8 @@ write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source,
/* Select a width if none was specified. The idea here is to always
print something. */
+ if (w == DEFAULT_WIDTH)
+ w = default_width_for_integer (len);
if (w == 0)
w = ((digits < m) ? m : digits) + nsign;
@@ -1187,13 +1191,13 @@ write_b (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
{
p = btoa_big (source, itoa_buf, len, &n);
- write_boz (dtp, f, p, n);
+ write_boz (dtp, f, p, n, len);
}
else
{
n = extract_uint (source, len);
p = btoa (n, itoa_buf, sizeof (itoa_buf));
- write_boz (dtp, f, p, n);
+ write_boz (dtp, f, p, n, len);
}
}
@@ -1208,13 +1212,13 @@ write_o (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
{
p = otoa_big (source, itoa_buf, len, &n);
- write_boz (dtp, f, p, n);
+ write_boz (dtp, f, p, n, len);
}
else
{
n = extract_uint (source, len);
p = otoa (n, itoa_buf, sizeof (itoa_buf));
- write_boz (dtp, f, p, n);
+ write_boz (dtp, f, p, n, len);
}
}
@@ -1228,13 +1232,13 @@ write_z (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
if (len > (int) sizeof (GFC_UINTEGER_LARGEST))
{
p = ztoa_big (source, itoa_buf, len, &n);
- write_boz (dtp, f, p, n);
+ write_boz (dtp, f, p, n, len);
}
else
{
n = extract_uint (source, len);
p = gfc_xtoa (n, itoa_buf, sizeof (itoa_buf));
- write_boz (dtp, f, p, n);
+ write_boz (dtp, f, p, n, len);
}
}
@@ -1504,7 +1508,7 @@ size_from_kind (st_parameter_dt *dtp, const fnode *f, int kind)
{
int size;
- if (f->format == FMT_F && f->u.real.w == 0)
+ if ((f->format == FMT_F && f->u.real.w == 0) || f->u.real.w == DEFAULT_WIDTH)
{
switch (kind)
{
diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def
index 7f0aa1d..73dc910 100644
--- a/libgfortran/io/write_float.def
+++ b/libgfortran/io/write_float.def
@@ -113,7 +113,8 @@ determine_precision (st_parameter_dt * d
static void
build_float_string (st_parameter_dt *dtp, const fnode *f, char *buffer,
size_t size, int nprinted, int precision, int sign_bit,
- bool zero_flag, int npad, char *result, size_t *len)
+ bool zero_flag, int npad, int default_width, char *result,
+ size_t *len)
{
char *put;
char *digits;
@@ -132,8 +133,17 @@ build_float_string (st_parameter_dt *dtp
sign_t sign;
ft = f->format;
- w = f->u.real.w;
- d = f->u.real.d;
+ if (f->u.real.w == DEFAULT_WIDTH)
+ /* This codepath can only be reached with -fdec-format-defaults. */
+ {
+ w = default_width;
+ d = precision;
+ }
+ else
+ {
+ w = f->u.real.w;
+ d = f->u.real.d;
+ }
p = dtp->u.p.scale_factor;
*len = 0;
@@ -959,6 +969,11 @@ determine_en_precision (st_parameter_dt
int save_scale_factor;\
volatile GFC_REAL_ ## x temp;\
save_scale_factor = dtp->u.p.scale_factor;\
+ if (w == DEFAULT_WIDTH)\
+ {\
+ w = default_width;\
+ d = precision;\
+ }\
switch (dtp->u.p.current_unit->round_status)\
{\
case ROUND_ZERO:\
@@ -1034,7 +1049,8 @@ determine_en_precision (st_parameter_dt
nprinted = FDTOA(y,precision,m);\
}\
build_float_string (dtp, &newf, buffer, size, nprinted, precision,\
- sign_bit, zero_flag, npad, result, res_len);\
+ sign_bit, zero_flag, npad, default_width,\
+ result, res_len);\
dtp->u.p.scale_factor = save_scale_factor;\
}\
else\
@@ -1044,7 +1060,8 @@ determine_en_precision (st_parameter_dt
else\
nprinted = DTOA(y,precision,m);\
build_float_string (dtp, f, buffer, size, nprinted, precision,\
- sign_bit, zero_flag, npad, result, res_len);\
+ sign_bit, zero_flag, npad, default_width,\
+ result, res_len);\
}\
}\
@@ -1058,6 +1075,16 @@ get_float_string (st_parameter_dt *dtp,
{
int sign_bit, nprinted;
bool zero_flag;
+ int default_width = 0;
+
+ if (f->u.real.w == DEFAULT_WIDTH)
+ /* This codepath can only be reached with -fdec-format-defaults. The default
+ * values are based on those used in the Oracle Fortran compiler.
+ */
+ {
+ default_width = default_width_for_float (kind);
+ precision = default_precision_for_float (kind);
+ }
switch (kind)
{

View File

@ -1,61 +0,0 @@
commit 79fa567e234585dc6a71f9bd069101c993513f3e
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Thu Apr 22 15:46:51 2021 +0100
libstdc++: Reject std::make_shared<T[]> [PR 99006]
Prior to C++20 it should be ill-formed to use std::make_shared with an
array type (and we don't support the C++20 feature to make it valid yet
anyway).
libstdc++-v3/ChangeLog:
PR libstdc++/99006
* include/bits/shared_ptr.h (allocate_shared): Assert that _Tp
is not an array type.
* include/bits/shared_ptr_base.h (__allocate_shared): Likewise.
* testsuite/20_util/shared_ptr/creation/99006.cc: New test.
(cherry picked from commit 55650236cd97d81f42f9fdb4f6bcb12babafe51f)
diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
index 281600b2901..4ddc52ae723 100644
--- a/libstdc++-v3/include/bits/shared_ptr.h
+++ b/libstdc++-v3/include/bits/shared_ptr.h
@@ -698,6 +698,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline shared_ptr<_Tp>
allocate_shared(const _Alloc& __a, _Args&&... __args)
{
+ static_assert(!is_array<_Tp>::value, "make_shared<T[]> not supported");
+
return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
std::forward<_Args>(__args)...);
}
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index 0367c2d51a5..8af6e9fb11c 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -1822,6 +1822,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline __shared_ptr<_Tp, _Lp>
__allocate_shared(const _Alloc& __a, _Args&&... __args)
{
+ static_assert(!is_array<_Tp>::value, "make_shared<T[]> not supported");
+
return __shared_ptr<_Tp, _Lp>(_Sp_alloc_shared_tag<_Alloc>{__a},
std::forward<_Args>(__args)...);
}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc
new file mode 100644
index 00000000000..d5f7a5da5e9
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc
@@ -0,0 +1,9 @@
+// FIXME: This should use { target { ! c++20 } }
+// { dg-do compile }
+
+#include <memory>
+
+auto p = std::make_shared<int[]>(2); // { dg-error "here" }
+auto q = std::make_shared<int[2]>(1, 2); // { dg-error "here" }
+
+// { dg-prune-output "static assertion failed" }

View File

@ -1,844 +0,0 @@
commit fe7c3ecff1f9c0520090a77fa824d8c5d9dbec12
Author: Jakub Jelinek <jakub@redhat.com>
Date: Fri Dec 3 11:03:30 2021 +0100
pch: Add support for PCH for relocatable executables [PR71934]
So, if we want to make PCH work for PIEs, I'd say we can:
1) add a new GTY option, say callback, which would act like
skip for non-PCH and for PCH would make us skip it but
remember for address bias translation
2) drop the skip for tree_translation_unit_decl::language
3) change get_unnamed_section to have const char * as
last argument instead of const void *, change
unnamed_section::data also to const char * and update
everything related to that
4) maybe add a host hook whether it is ok to support binaries
changing addresses (the only thing I'm worried is if
some host that uses function descriptors allocates them
dynamically instead of having them somewhere in the
executable)
5) maybe add a gengtype warning if it sees in GTY tracked
structure a function pointer without that new callback
option
Here is 1), 2), 3) implemented.
Note, on stdc++.h.gch/O2g.gch there are just those 10 relocations without
the second patch, with it a few more, but nothing huge. And for non-PIEs
there isn't really any extra work on the load side except freading two scalar
values and fseek.
2021-12-03 Jakub Jelinek <jakub@redhat.com>
PR pch/71934
gcc/
* ggc.h (gt_pch_note_callback): Declare.
* gengtype.h (enum typekind): Add TYPE_CALLBACK.
(callback_type): Declare.
* gengtype.c (dbgprint_count_type_at): Handle TYPE_CALLBACK.
(callback_type): New variable.
(process_gc_options): Add CALLBACK argument, handle callback
option.
(set_gc_used_type): Adjust process_gc_options caller, if callback,
set type to &callback_type.
(output_mangled_typename): Handle TYPE_CALLBACK.
(walk_type): Likewise. Handle callback option.
(write_types_process_field): Handle TYPE_CALLBACK.
(write_types_local_user_process_field): Likewise.
(write_types_local_process_field): Likewise.
(write_root): Likewise.
(dump_typekind): Likewise.
(dump_type): Likewise.
* gengtype-state.c (type_lineloc): Handle TYPE_CALLBACK.
(state_writer::write_state_callback_type): New method.
(state_writer::write_state_type): Handle TYPE_CALLBACK.
(read_state_callback_type): New function.
(read_state_type): Handle TYPE_CALLBACK.
* ggc-common.c (callback_vec): New variable.
(gt_pch_note_callback): New function.
(gt_pch_save): Stream out gt_pch_save function address and relocation
table.
(gt_pch_restore): Stream in saved gt_pch_save function address and
relocation table and apply relocations if needed.
* doc/gty.texi (callback): Document new GTY option.
* varasm.c (get_unnamed_section): Change callback argument's type and
last argument's type from const void * to const char *.
(output_section_asm_op): Change argument's type from const void *
to const char *, remove unnecessary cast.
* tree-core.h (struct tree_translation_unit_decl): Drop GTY((skip))
from language member.
* output.h (unnamed_section_callback): Change argument type from
const void * to const char *.
(struct unnamed_section): Use GTY((callback)) instead of GTY((skip))
for callback member. Change data member type from const void *
to const char *.
(struct noswitch_section): Use GTY((callback)) instead of GTY((skip))
for callback member.
(get_unnamed_section): Change callback argument's type and
last argument's type from const void * to const char *.
(output_section_asm_op): Change argument's type from const void *
to const char *.
* config/avr/avr.c (avr_output_progmem_section_asm_op): Likewise.
Remove unneeded cast.
* config/darwin.c (output_objc_section_asm_op): Change argument's type
from const void * to const char *.
* config/pa/pa.c (som_output_text_section_asm_op): Likewise.
(som_output_comdat_data_section_asm_op): Likewise.
* config/rs6000/rs6000.c (rs6000_elf_output_toc_section_asm_op):
Likewise.
(rs6000_xcoff_output_readonly_section_asm_op): Likewise. Instead
of dereferencing directive hardcode variable names and decide based on
whether directive is NULL or not.
(rs6000_xcoff_output_readwrite_section_asm_op): Change argument's type
from const void * to const char *.
(rs6000_xcoff_output_tls_section_asm_op): Likewise. Instead
of dereferencing directive hardcode variable names and decide based on
whether directive is NULL or not.
(rs6000_xcoff_output_toc_section_asm_op): Change argument's type
from const void * to const char *.
(rs6000_xcoff_asm_init_sections): Adjust get_unnamed_section callers.
gcc/c-family/
* c-pch.c (struct c_pch_validity): Remove pch_init member.
(pch_init): Don't initialize v.pch_init.
(c_common_valid_pch): Don't warn and punt if .text addresses change.
libcpp/
* include/line-map.h (class line_maps): Add GTY((callback)) to
reallocator and round_alloc_size members.
commit 4dc6d19222581c77a174d44d97507d234fb7e39b
Author: Jakub Jelinek <jakub@redhat.com>
Date: Mon Dec 6 11:18:58 2021 +0100
avr: Fix AVR build [PR71934]
On Mon, Dec 06, 2021 at 11:00:30AM +0100, Martin Liška wrote:
> Jakub, I think the patch broke avr-linux target:
>
> g++ -fno-PIE -c -g -DIN_GCC -DCROSS_DIRECTORY_STRUCTURE -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wno-erro
> /home/marxin/Programming/gcc/gcc/config/avr/avr.c: In function void avr_output_data_section_asm_op(const void*):
> /home/marxin/Programming/gcc/gcc/config/avr/avr.c:10097:26: error: invalid conversion from const void* to const char* [-fpermissive]
This patch fixes that.
2021-12-06 Jakub Jelinek <jakub@redhat.com>
PR pch/71934
* config/avr/avr.c (avr_output_data_section_asm_op,
avr_output_bss_section_asm_op): Change argument type from const void *
to const char *.
diff --git a/gcc/c-family/c-pch.c b/gcc/c-family/c-pch.c
index 5da60423354..2cafa1387bb 100644
--- a/gcc/c-family/c-pch.c
+++ b/gcc/c-family/c-pch.c
@@ -58,7 +58,6 @@ struct c_pch_validity
{
unsigned char debug_info_type;
signed char match[MATCH_SIZE];
- void (*pch_init) (void);
size_t target_data_length;
};
@@ -123,7 +122,6 @@ pch_init (void)
gcc_assert (v.match[i] == *pch_matching[i].flag_var);
}
}
- v.pch_init = &pch_init;
target_validity = targetm.get_pch_validity (&v.target_data_length);
if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1
@@ -287,20 +285,6 @@ c_common_valid_pch (cpp_reader *pfile, c
}
}
- /* If the text segment was not loaded at the same address as it was
- when the PCH file was created, function pointers loaded from the
- PCH will not be valid. We could in theory remap all the function
- pointers, but no support for that exists at present.
- Since we have the same executable, it should only be necessary to
- check one function. */
- if (v.pch_init != &pch_init)
- {
- if (cpp_get_options (pfile)->warn_invalid_pch)
- cpp_error (pfile, CPP_DL_WARNING,
- "%s: had text segment at different address", name);
- return 2;
- }
-
/* Check the target-specific validity data. */
{
void *this_file_data = xmalloc (v.target_data_length);
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 200701a583c..6ba038881d6 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -10114,10 +10114,9 @@ avr_output_bss_section_asm_op (const void *data)
/* Unnamed section callback for progmem*.data sections. */
static void
-avr_output_progmem_section_asm_op (const void *data)
+avr_output_progmem_section_asm_op (const char *data)
{
- fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n",
- (const char*) data);
+ fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n", data);
}
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index c5ba7927ce1..8ad5b26c980 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -134,7 +134,7 @@ int emit_aligned_common = false;
DIRECTIVE is as for output_section_asm_op. */
static void
-output_objc_section_asm_op (const void *directive)
+output_objc_section_asm_op (const char *directive)
{
static bool been_here = false;
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index f22d25a4066..2b10ef34061 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -10009,7 +10009,7 @@ pa_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
to the default text subspace. */
static void
-som_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED)
+som_output_text_section_asm_op (const char *data ATTRIBUTE_UNUSED)
{
gcc_assert (TARGET_SOM);
if (TARGET_GAS)
@@ -10053,7 +10053,7 @@ som_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED)
sections. This function is only used with SOM. */
static void
-som_output_comdat_data_section_asm_op (const void *data)
+som_output_comdat_data_section_asm_op (const char *data)
{
in_section = NULL;
output_section_asm_op (data);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 945157b1c1a..34089743759 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -20599,7 +20599,7 @@ rs6000_ms_bitfield_layout_p (const_tree record_type)
/* A get_unnamed_section callback, used for switching to toc_section. */
static void
-rs6000_elf_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
+rs6000_elf_output_toc_section_asm_op (const char *data ATTRIBUTE_UNUSED)
{
if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
&& TARGET_MINIMAL_TOC)
@@ -21303,35 +21303,39 @@ rs6000_xcoff_asm_globalize_label (FILE *stream, const char *name)
points to the section string variable. */
static void
-rs6000_xcoff_output_readonly_section_asm_op (const void *directive)
+rs6000_xcoff_output_readonly_section_asm_op (const char *directive)
{
fprintf (asm_out_file, "\t.csect %s[RO],%s\n",
- *(const char *const *) directive,
+ directive
+ ? xcoff_private_rodata_section_name
+ : xcoff_read_only_section_name,
XCOFF_CSECT_DEFAULT_ALIGNMENT_STR);
}
/* Likewise for read-write sections. */
static void
-rs6000_xcoff_output_readwrite_section_asm_op (const void *directive)
+rs6000_xcoff_output_readwrite_section_asm_op (const char *)
{
fprintf (asm_out_file, "\t.csect %s[RW],%s\n",
- *(const char *const *) directive,
+ xcoff_private_data_section_name,
XCOFF_CSECT_DEFAULT_ALIGNMENT_STR);
}
static void
-rs6000_xcoff_output_tls_section_asm_op (const void *directive)
+rs6000_xcoff_output_tls_section_asm_op (const char *directive)
{
fprintf (asm_out_file, "\t.csect %s[TL],%s\n",
- *(const char *const *) directive,
+ directive
+ ? xcoff_private_data_section_name
+ : xcoff_tls_data_section_name,
XCOFF_CSECT_DEFAULT_ALIGNMENT_STR);
}
/* A get_unnamed_section callback, used for switching to toc_section. */
static void
-rs6000_xcoff_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
+rs6000_xcoff_output_toc_section_asm_op (const char *data ATTRIBUTE_UNUSED)
{
if (TARGET_MINIMAL_TOC)
{
@@ -21358,26 +21362,26 @@ rs6000_xcoff_asm_init_sections (void)
{
read_only_data_section
= get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
- &xcoff_read_only_section_name);
+ NULL);
private_data_section
= get_unnamed_section (SECTION_WRITE,
rs6000_xcoff_output_readwrite_section_asm_op,
- &xcoff_private_data_section_name);
+ NULL);
read_only_private_data_section
= get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
- &xcoff_private_rodata_section_name);
+ "");
tls_data_section
= get_unnamed_section (SECTION_TLS,
rs6000_xcoff_output_tls_section_asm_op,
- &xcoff_tls_data_section_name);
+ NULL);
tls_private_data_section
= get_unnamed_section (SECTION_TLS,
rs6000_xcoff_output_tls_section_asm_op,
- &xcoff_private_data_section_name);
+ "");
toc_section
= get_unnamed_section (0, rs6000_xcoff_output_toc_section_asm_op, NULL);
diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index b996ff2c44e..ca2c8404894 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -205,6 +205,15 @@ If @code{skip} is applied to a field, the type machinery will ignore it.
This is somewhat dangerous; the only safe use is in a union when one
field really isn't ever used.
+@findex callback
+@item callback
+
+@code{callback} should be applied to fields with pointer to function type
+and causes the field to be ignored similarly to @code{skip}, except when
+writing PCH and the field is non-NULL it will remember the field's address
+for relocation purposes if the process writing PCH has different load base
+from a process reading PCH.
+
@findex for_user
@item for_user
diff --git a/gcc/gengtype-state.c b/gcc/gengtype-state.c
index ac9d536963f..36a96e84574 100644
--- a/gcc/gengtype-state.c
+++ b/gcc/gengtype-state.c
@@ -57,6 +57,7 @@ type_lineloc (const_type_p ty)
case TYPE_STRING:
case TYPE_POINTER:
case TYPE_ARRAY:
+ case TYPE_CALLBACK:
return NULL;
default:
gcc_unreachable ();
@@ -171,6 +172,7 @@ private:
void write_state_version (const char *version);
void write_state_scalar_type (type_p current);
void write_state_string_type (type_p current);
+ void write_state_callback_type (type_p current);
void write_state_undefined_type (type_p current);
void write_state_struct_union_type (type_p current, const char *kindstr);
void write_state_struct_type (type_p current);
@@ -898,6 +900,20 @@ state_writer::write_state_string_type (type_p current)
fatal ("Unexpected type in write_state_string_type");
}
+/* Write the callback type. There is only one such thing! */
+void
+state_writer::write_state_callback_type (type_p current)
+{
+ if (current == &callback_type)
+ {
+ write_any_indent (0);
+ fprintf (state_file, "callback ");
+ write_state_common_type_content (current);
+ }
+ else
+ fatal ("Unexpected type in write_state_callback_type");
+}
+
/* Write an undefined type. */
void
state_writer::write_state_undefined_type (type_p current)
@@ -1143,6 +1159,9 @@ state_writer::write_state_type (type_p current)
case TYPE_STRING:
write_state_string_type (current);
break;
+ case TYPE_CALLBACK:
+ write_state_callback_type (current);
+ break;
}
}
@@ -1477,6 +1496,14 @@ read_state_string_type (type_p *type)
read_state_common_type_content (*type);
}
+/* Read the callback_type. */
+static void
+read_state_callback_type (type_p *type)
+{
+ *type = &callback_type;
+ read_state_common_type_content (*type);
+}
+
/* Read a lang_bitmap representing a set of GCC front-end languages. */
static void
@@ -1834,6 +1861,11 @@ read_state_type (type_p *current)
next_state_tokens (1);
read_state_string_type (current);
}
+ else if (state_token_is_name (t0, "callback"))
+ {
+ next_state_tokens (1);
+ read_state_callback_type (current);
+ }
else if (state_token_is_name (t0, "undefined"))
{
*current = XCNEW (struct type);
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index a77cfd92bfa..b9daaa43689 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -172,6 +172,7 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
int nb_struct = 0, nb_union = 0, nb_array = 0, nb_pointer = 0;
int nb_lang_struct = 0;
int nb_user_struct = 0, nb_undefined = 0;
+ int nb_callback = 0;
type_p p = NULL;
for (p = t; p; p = p->next)
{
@@ -202,6 +203,9 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
case TYPE_ARRAY:
nb_array++;
break;
+ case TYPE_CALLBACK:
+ nb_callback++;
+ break;
case TYPE_LANG_STRUCT:
nb_lang_struct++;
break;
@@ -217,6 +221,8 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
fprintf (stderr, "@@%%@@ %d structs, %d unions\n", nb_struct, nb_union);
if (nb_pointer > 0 || nb_array > 0)
fprintf (stderr, "@@%%@@ %d pointers, %d arrays\n", nb_pointer, nb_array);
+ if (nb_callback > 0)
+ fprintf (stderr, "@@%%@@ %d callbacks\n", nb_callback);
if (nb_lang_struct > 0)
fprintf (stderr, "@@%%@@ %d lang_structs\n", nb_lang_struct);
if (nb_user_struct > 0)
@@ -495,6 +501,10 @@ struct type scalar_char = {
TYPE_SCALAR, 0, 0, 0, GC_USED, {0}
};
+struct type callback_type = {
+ TYPE_CALLBACK, 0, 0, 0, GC_USED, {0}
+};
+
/* Lists of various things. */
pair_p typedefs = NULL;
@@ -1464,7 +1474,7 @@ static void set_gc_used (pair_p);
static void
process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef,
- int *length, int *skip, type_p *nested_ptr)
+ int *length, int *skip, int *callback, type_p *nested_ptr)
{
options_p o;
for (o = opt; o; o = o->next)
@@ -1478,6 +1488,8 @@ process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef,
*length = 1;
else if (strcmp (o->name, "skip") == 0)
*skip = 1;
+ else if (strcmp (o->name, "callback") == 0)
+ *callback = 1;
else if (strcmp (o->name, "nested_ptr") == 0
&& o->kind == OPTION_NESTED)
*nested_ptr = ((const struct nested_ptr_data *) o->info.nested)->type;
@@ -1526,7 +1538,7 @@ set_gc_used_type (type_p t, enum gc_used_enum level,
type_p dummy2;
bool allow_undefined_field_types = (t->kind == TYPE_USER_STRUCT);
- process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy,
+ process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, &dummy,
&dummy2);
if (t->u.s.base_class)
@@ -1542,9 +1554,10 @@ set_gc_used_type (type_p t, enum gc_used_enum level,
int maybe_undef = 0;
int length = 0;
int skip = 0;
+ int callback = 0;
type_p nested_ptr = NULL;
process_gc_options (f->opt, level, &maybe_undef, &length, &skip,
- &nested_ptr);
+ &callback, &nested_ptr);
if (nested_ptr && f->type->kind == TYPE_POINTER)
set_gc_used_type (nested_ptr, GC_POINTED_TO);
@@ -1554,6 +1567,8 @@ set_gc_used_type (type_p t, enum gc_used_enum level,
set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO);
else if (skip)
; /* target type is not used through this field */
+ else if (callback)
+ f->type = &callback_type;
else
set_gc_used_type (f->type, GC_USED, allow_undefined_field_types);
}
@@ -2519,6 +2534,7 @@ output_mangled_typename (outf_p of, const_type_p t)
{
case TYPE_NONE:
case TYPE_UNDEFINED:
+ case TYPE_CALLBACK:
gcc_unreachable ();
break;
case TYPE_POINTER:
@@ -2719,6 +2735,8 @@ walk_type (type_p t, struct walk_type_data *d)
;
else if (strcmp (oo->name, "for_user") == 0)
;
+ else if (strcmp (oo->name, "callback") == 0)
+ ;
else
error_at_line (d->line, "unknown option `%s'\n", oo->name);
@@ -2744,6 +2762,7 @@ walk_type (type_p t, struct walk_type_data *d)
{
case TYPE_SCALAR:
case TYPE_STRING:
+ case TYPE_CALLBACK:
d->process_field (t, d);
break;
@@ -3275,6 +3294,7 @@ write_types_process_field (type_p f, const struct walk_type_data *d)
break;
case TYPE_SCALAR:
+ case TYPE_CALLBACK:
break;
case TYPE_ARRAY:
@@ -3820,6 +3840,7 @@ write_types_local_user_process_field (type_p f, const struct walk_type_data *d)
break;
case TYPE_SCALAR:
+ case TYPE_CALLBACK:
break;
case TYPE_ARRAY:
@@ -3906,6 +3927,13 @@ write_types_local_process_field (type_p f, const struct walk_type_data *d)
case TYPE_SCALAR:
break;
+ case TYPE_CALLBACK:
+ oprintf (d->of, "%*sif ((void *)(%s) == this_obj)\n", d->indent, "",
+ d->prev_val[3]);
+ oprintf (d->of, "%*s gt_pch_note_callback (&(%s), this_obj);\n",
+ d->indent, "", d->val);
+ break;
+
case TYPE_ARRAY:
case TYPE_NONE:
case TYPE_UNDEFINED:
@@ -4434,6 +4462,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
case TYPE_UNDEFINED:
case TYPE_UNION:
case TYPE_LANG_STRUCT:
+ case TYPE_CALLBACK:
error_at_line (line, "global `%s' is unimplemented type", name);
}
}
@@ -4728,6 +4757,9 @@ dump_typekind (int indent, enum typekind kind)
case TYPE_ARRAY:
printf ("TYPE_ARRAY");
break;
+ case TYPE_CALLBACK:
+ printf ("TYPE_CALLBACK");
+ break;
case TYPE_LANG_STRUCT:
printf ("TYPE_LANG_STRUCT");
break;
@@ -4894,6 +4926,7 @@ dump_type (int indent, type_p t)
t->u.scalar_is_char ? "true" : "false");
break;
case TYPE_STRING:
+ case TYPE_CALLBACK:
break;
case TYPE_STRUCT:
case TYPE_UNION:
diff --git a/gcc/gengtype.h b/gcc/gengtype.h
index 8a7a54957ea..8fa7064ca85 100644
--- a/gcc/gengtype.h
+++ b/gcc/gengtype.h
@@ -154,6 +154,9 @@ enum typekind {
TYPE_UNION, /* Type for GTY-ed discriminated unions. */
TYPE_POINTER, /* Pointer type to GTY-ed type. */
TYPE_ARRAY, /* Array of GTY-ed types. */
+ TYPE_CALLBACK, /* A function pointer that needs relocation if
+ the executable has been loaded at a different
+ address. */
TYPE_LANG_STRUCT, /* GCC front-end language specific structs.
Various languages may have homonymous but
different structs. */
@@ -331,6 +334,9 @@ extern struct type string_type;
extern struct type scalar_nonchar;
extern struct type scalar_char;
+/* The one and only TYPE_CALLBACK. */
+extern struct type callback_type;
+
/* Test if a type is a union, either a plain one or a language
specific one. */
#define UNION_P(x) \
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index b6abed1d9a2..7c998e95473 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -256,6 +256,7 @@ saving_hasher::equal (const ptr_data *p1
}
static hash_table<saving_hasher> *saving_htab;
+static vec<void *> callback_vec;
/* Register an object in the hash table. */
@@ -288,6 +289,23 @@ gt_pch_note_object (void *obj, void *not
return 1;
}
+/* Register address of a callback pointer. */
+void
+gt_pch_note_callback (void *obj, void *base)
+{
+ void *ptr;
+ memcpy (&ptr, obj, sizeof (void *));
+ if (ptr != NULL)
+ {
+ struct ptr_data *data
+ = (struct ptr_data *)
+ saving_htab->find_with_hash (base, POINTER_HASH (base));
+ gcc_assert (data);
+ callback_vec.safe_push ((char *) data->new_addr
+ + ((char *) obj - (char *) base));
+ }
+}
+
/* Register an object in the hash table. */
void
@@ -582,10 +600,20 @@ gt_pch_save (FILE *f)
ggc_pch_finish (state.d, state.f);
gt_pch_fixup_stringpool ();
+ unsigned num_callbacks = callback_vec.length ();
+ void (*pch_save) (FILE *) = &gt_pch_save;
+ if (fwrite (&pch_save, sizeof (pch_save), 1, f) != 1
+ || fwrite (&num_callbacks, sizeof (num_callbacks), 1, f) != 1
+ || (num_callbacks
+ && fwrite (callback_vec.address (), sizeof (void *), num_callbacks,
+ f) != num_callbacks))
+ fatal_error (input_location, "cannot write PCH file: %m");
+
XDELETE (state.ptrs);
XDELETE (this_object);
delete saving_htab;
saving_htab = NULL;
+ callback_vec.release ();
}
/* Read the state of the compiler back in from F. */
@@ -639,6 +667,30 @@ gt_pch_restore (FILE *f)
ggc_pch_read (f, mmi.preferred_base);
gt_pch_restore_stringpool ();
+
+ void (*pch_save) (FILE *);
+ unsigned num_callbacks;
+ if (fread (&pch_save, sizeof (pch_save), 1, f) != 1
+ || fread (&num_callbacks, sizeof (num_callbacks), 1, f) != 1)
+ fatal_error (input_location, "cannot read PCH file: %m");
+ if (pch_save != &gt_pch_save)
+ {
+ uintptr_t bias = (uintptr_t) &gt_pch_save - (uintptr_t) pch_save;
+ void **ptrs = XNEWVEC (void *, num_callbacks);
+ unsigned i;
+
+ if (fread (ptrs, sizeof (void *), num_callbacks, f) != num_callbacks)
+ fatal_error (input_location, "cannot read PCH file: %m");
+ for (i = 0; i < num_callbacks; ++i)
+ {
+ memcpy (&pch_save, ptrs[i], sizeof (pch_save));
+ pch_save = (void (*) (FILE *)) ((uintptr_t) pch_save + bias);
+ memcpy (ptrs[i], &pch_save, sizeof (pch_save));
+ }
+ XDELETE (ptrs);
+ }
+ else if (fseek (f, num_callbacks * sizeof (void *), SEEK_CUR) != 0)
+ fatal_error (input_location, "cannot read PCH file: %m");
}
/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is not present.
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 5e921d957fd..c005f7e0412 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -46,6 +46,10 @@ typedef void (*gt_handle_reorder) (void *, void *, gt_pointer_operator,
/* Used by the gt_pch_n_* routines. Register an object in the hash table. */
extern int gt_pch_note_object (void *, void *, gt_note_pointers);
+/* Used by the gt_pch_p_* routines. Register address of a callback
+ pointer. */
+extern void gt_pch_note_callback (void *, void *);
+
/* Used by the gt_pch_n_* routines. Register that an object has a reorder
function. */
extern void gt_pch_note_reorder (void *, void *, gt_handle_reorder);
diff --git a/gcc/output.h b/gcc/output.h
index 8f6f15308f4..4a23795bf7e 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -456,7 +456,7 @@ struct GTY(()) named_section {
/* A callback that writes the assembly code for switching to an unnamed
section. The argument provides callback-specific data. */
-typedef void (*unnamed_section_callback) (const void *);
+typedef void (*unnamed_section_callback) (const char *);
/* Information about a SECTION_UNNAMED section. */
struct GTY(()) unnamed_section {
@@ -464,8 +464,8 @@ struct GTY(()) unnamed_section {
/* The callback used to switch to the section, and the data that
should be passed to the callback. */
- unnamed_section_callback GTY ((skip)) callback;
- const void *GTY ((skip)) data;
+ unnamed_section_callback GTY ((callback)) callback;
+ const char *data;
/* The next entry in the chain of unnamed sections. */
section *next;
@@ -489,7 +489,7 @@ struct GTY(()) noswitch_section {
struct section_common common;
/* The callback used to assemble decls in this section. */
- noswitch_section_callback GTY ((skip)) callback;
+ noswitch_section_callback GTY ((callback)) callback;
};
/* Information about a section, which may be named or unnamed. */
@@ -524,8 +524,8 @@ extern GTY(()) section *bss_noswitch_sec
extern GTY(()) section *in_section;
extern GTY(()) bool in_cold_section_p;
-extern section *get_unnamed_section (unsigned int, void (*) (const void *),
- const void *);
+extern section *get_unnamed_section (unsigned int, void (*) (const char *),
+ const char *);
extern section *get_section (const char *, unsigned int, tree);
extern section *get_named_section (tree, const char *, int);
extern section *get_variable_section (tree, bool);
@@ -546,7 +546,7 @@ extern section *get_cdtor_priority_secti
extern bool unlikely_text_section_p (section *);
extern void switch_to_section (section *);
-extern void output_section_asm_op (const void *);
+extern void output_section_asm_op (const char *);
extern void record_tm_clone_pair (tree, tree);
extern void finish_tm_clone_pairs (void);
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 8ab119dc9a2..91ae5237d7e 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1961,7 +1961,7 @@ struct GTY(()) tree_function_decl {
struct GTY(()) tree_translation_unit_decl {
struct tree_decl_common common;
/* Source language of this translation unit. Used for DWARF output. */
- const char * GTY((skip(""))) language;
+ const char *language;
/* TODO: Non-optimization used to build this translation unit. */
/* TODO: Root of a partial DWARF tree for global types and decls. */
};
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 9315e2c6936..aff93ca5de9 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -250,8 +250,8 @@ object_block_hasher::hash (object_block *old)
/* Return a new unnamed section with the given fields. */
section *
-get_unnamed_section (unsigned int flags, void (*callback) (const void *),
- const void *data)
+get_unnamed_section (unsigned int flags, void (*callback) (const char *),
+ const char *data)
{
section *sect;
@@ -7778,9 +7778,9 @@ file_end_indicate_split_stack (void)
a get_unnamed_section callback. */
void
-output_section_asm_op (const void *directive)
+output_section_asm_op (const char *directive)
{
- fprintf (asm_out_file, "%s\n", (const char *) directive);
+ fprintf (asm_out_file, "%s\n", directive);
}
/* Emit assembly code to switch to section NEW_SECTION. Do nothing if
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 8b5e2f82982..bc40e333579 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -758,11 +758,11 @@ struct GTY(()) line_maps {
/* If non-null, the allocator to use when resizing 'maps'. If null,
xrealloc is used. */
- line_map_realloc reallocator;
+ line_map_realloc GTY((callback)) reallocator;
/* The allocators' function used to know the actual size it
allocated, for a certain allocation size requested. */
- line_map_round_alloc_size_func round_alloc_size;
+ line_map_round_alloc_size_func GTY((callback)) round_alloc_size;
struct location_adhoc_data_map location_adhoc_data_map;
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 6ba038881d6..1c2f7d564e7 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -10089,7 +10089,7 @@ avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
to track need of __do_copy_data. */
static void
-avr_output_data_section_asm_op (const void *data)
+avr_output_data_section_asm_op (const char *data)
{
avr_need_copy_data_p = true;
@@ -10102,7 +10102,7 @@ avr_output_data_section_asm_op (const void *data)
to track need of __do_clear_bss. */
static void
-avr_output_bss_section_asm_op (const void *data)
+avr_output_bss_section_asm_op (const char *data)
{
avr_need_clear_bss_p = true;

View File

@ -1,98 +0,0 @@
From b005000525ab0a5116d21217c41fb1da5bd03796 Mon Sep 17 00:00:00 2001
From: Jonathan Wakely <jwakely@redhat.com>
Date: Fri, 6 May 2022 21:19:17 +0100
Subject: [PATCH] libstdc++: Fix deserialization for std::normal_distribution
[PR105502]
This fixes a regression in std::normal_distribution deserialization that
caused the object to be left unchanged if the __state_avail value read
from the stream was false.
libstdc++-v3/ChangeLog:
PR libstdc++/105502
* include/bits/random.tcc
(operator>>(basic_istream<C,T>&, normal_distribution<R>&)):
Update state when __state_avail is false.
* testsuite/26_numerics/random/normal_distribution/operators/serialize.cc:
Check that deserialized object equals serialized one.
(cherry picked from commit 909ef4e2727ddc50a32d6ad379a1f1ccc1043c6a)
---
libstdc++-v3/include/bits/random.tcc | 2 +-
.../operators/serialize.cc | 36 ++++++++++++++++++-
2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc
index 0a299baedc5..0f758671f69 100644
--- a/libstdc++-v3/include/bits/random.tcc
+++ b/libstdc++-v3/include/bits/random.tcc
@@ -1941,7 +1941,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool __saved_avail;
if (__is >> __mean >> __stddev >> __saved_avail)
{
- if (__saved_avail && (__is >> __x._M_saved))
+ if (!__saved_avail || (__is >> __x._M_saved))
{
__x._M_saved_available = __saved_avail;
__x.param(typename normal_distribution<_RealType>::
diff --git a/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc b/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc
index a65d4004161..8cc70886bc7 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc
@@ -25,6 +25,7 @@
#include <random>
#include <sstream>
+#include <testsuite_hooks.h>
void
test01()
@@ -37,10 +38,43 @@ test01()
str << u;
str >> v;
+ VERIFY( u == v );
+}
+
+void
+test_pr105502()
+{
+ // PR libstdc++/105502 std::normal_distribution deserialization issue
+ std::stringstream str;
+ std::normal_distribution<> d{1, 2}, d2;
+ std::minstd_rand0 g;
+ str << d;
+ VERIFY( str );
+ str >> d2;
+ VERIFY( str );
+ VERIFY( d == d2 );
+
+ (void) d(g); // sets d._M_saved_available = true
+ str.str("");
+ str.clear();
+ str << d;
+ VERIFY( str );
+ str >> d2;
+ VERIFY( str );
+ VERIFY( d == d2 );
+
+ (void) d(g); // sets d._M_saved_available = false
+ str.str("");
+ str.clear();
+ str << d;
+ VERIFY( str );
+ str >> d2;
+ VERIFY( str );
+ VERIFY( d == d2 );
}
int main()
{
test01();
- return 0;
+ test_pr105502();
}
--
2.31.1

View File

@ -1,61 +0,0 @@
commit e150cbf591759af10f3d57acbe0eb381aafa00de
Author: Richard Biener <rguenther@suse.de>
Date: Thu Aug 17 13:10:14 2023 +0200
tree-optimization/111039 - abnormals and bit test merging
The following guards the bit test merging code in if-combine against
the appearance of SSA names used in abnormal PHIs.
PR tree-optimization/111039
* tree-ssa-ifcombine.cc (ifcombine_ifandif): Check for
SSA_NAME_OCCURS_IN_ABNORMAL_PHI.
* gcc.dg/pr111039.c: New testcase.
(cherry picked from commit 482551a79a3d3f107f6239679ee74655cfe8707e)
diff --git a/gcc/testsuite/gcc.dg/pr111039.c b/gcc/testsuite/gcc.dg/pr111039.c
new file mode 100644
index 00000000000..bec9983b35f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr111039.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+int _setjmp ();
+void abcd ();
+void abcde ();
+void compiler_corruption_function(int flags)
+{
+ int nowait = flags & 1048576, isexpand = flags & 8388608;
+ abcd();
+ _setjmp(flags);
+ if (nowait && isexpand)
+ flags &= 0;
+ abcde();
+}
--- a/gcc/tree-ssa-ifcombine.c
+++ b/gcc/tree-ssa-ifcombine.c
@@ -407,6 +407,9 @@ ifcombine_ifandif (basic_block inner_con
{
tree t, t2;
+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1))
+ return false;
+
/* Do it. */
gsi = gsi_for_stmt (inner_cond);
t = fold_build2 (LSHIFT_EXPR, TREE_TYPE (name1),
@@ -457,6 +460,10 @@ ifcombine_ifandif (basic_block inner_con
gimple_stmt_iterator gsi;
tree t;
+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1)
+ || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2))
+ return false;
+
/* Find the common name which is bit-tested. */
if (name1 == name2)
;

View File

@ -1,68 +0,0 @@
commit ad42dcf501e41713047cf6c47cbb1dd9f01088a4
Author: Richard Biener <rguenther@suse.de>
Date: Mon Aug 21 09:01:00 2023 +0200
tree-optimization/111070 - fix ICE with recent ifcombine fix
We now got test coverage for non-SSA name bits so the following amends
the SSA_NAME_OCCURS_IN_ABNORMAL_PHI checks.
PR tree-optimization/111070
* tree-ssa-ifcombine.cc (ifcombine_ifandif): Check we have
an SSA name before checking SSA_NAME_OCCURS_IN_ABNORMAL_PHI.
* gcc.dg/pr111070.c: New testcase.
(cherry picked from commit 966b0a96523fb7adbf498ac71df5e033c70dc546)
diff --git a/gcc/testsuite/gcc.dg/pr111070.c b/gcc/testsuite/gcc.dg/pr111070.c
new file mode 100644
index 00000000000..1ebc7adf782
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr111070.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+/* common */
+char c;
+/* arrays must be 8 byte aligned, regardless of size */
+char c_ary[1];
+
+/* data */
+char d = 1;
+char d_ary[1] = {1};
+
+int main ()
+{
+ if (((unsigned long)&c_ary[0] & 7) != 0)
+ return 1;
+ if (((unsigned long)&d_ary[0] & 7) != 0)
+ return 1;
+ return 0;
+}
--- a/gcc/tree-ssa-ifcombine.c
+++ b/gcc/tree-ssa-ifcombine.c
@@ -436,7 +436,8 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
{
tree t, t2;
- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1))
+ if (TREE_CODE (name1) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1))
return false;
/* Do it. */
@@ -495,8 +496,10 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
gimple_stmt_iterator gsi;
tree t;
- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1)
- || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2))
+ if ((TREE_CODE (name1) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1))
+ || (TREE_CODE (name2) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2)))
return false;
/* Find the common name which is bit-tested. */

View File

@ -1,71 +0,0 @@
commit 8c21b0d164f33d9d47acc26f4f9b99b53e3b1945
Author: Andreas Krebbel <krebbel@linux.ibm.com>
Date: Tue Nov 6 10:22:05 2018 +0000
S/390: Fix PR87723
gcc/ChangeLog:
2018-11-06 Andreas Krebbel <krebbel@linux.ibm.com>
PR target/87723
* config/s390/s390.md ("*r<noxa>sbg_di_rotl"): Remove mode
attributes for operands 3 and 4.
gcc/testsuite/ChangeLog:
2018-11-06 Andreas Krebbel <krebbel@linux.ibm.com>
PR target/87723
* gcc.target/s390/pr87723.c: New test.
From-SVN: r265832
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 8e7b285e1c3..4ffd438c07c 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -4230,7 +4230,7 @@ (define_insn "*r<noxa>sbg_di_rotl"
(match_operand:DI 4 "nonimmediate_operand" "0")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_Z10"
- "r<noxa>sbg\t%0,%1,%<bfstart>2,%<bfend>2,%b3"
+ "r<noxa>sbg\t%0,%1,%s2,%e2,%b3"
[(set_attr "op_type" "RIE")])
; rosbg, rxsbg
diff --git a/gcc/testsuite/gcc.target/s390/pr87723.c b/gcc/testsuite/gcc.target/s390/pr87723.c
new file mode 100644
index 00000000000..b0e8a5a3118
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr87723.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z196 -m64 -mzarch" } */
+
+unsigned long a;
+int b;
+void c(char* i) {
+ for (;;) {
+ char g = 0;
+ for (; g < 24; ++g)
+ b = a << g | a >> 64 - g;
+ {
+ char *d = i;
+ long h = b;
+ char e = 0;
+ for (; e < 8; ++e)
+ d[e] = h;
+ }
+ char *d = i;
+ signed e;
+ unsigned long f = 0;
+ e = 7;
+ for (; e; --e) {
+ f <<= 8;
+ f |= d[e];
+ }
+ for (; e < 8; ++e)
+ d[e] = f;
+ }
+}

View File

@ -1,254 +0,0 @@
commit 6001db79c477b03eacc7e7049560921fb54b7845
Author: Richard Sandiford <richard.sandiford@arm.com>
Date: Mon Sep 7 20:15:36 2020 +0100
lra: Avoid cycling on certain subreg reloads [PR96796]
This PR is about LRA cycling for a reload of the form:
----------------------------------------------------------------------------
Changing pseudo 196 in operand 1 of insn 103 on equiv [r105:DI*0x8+r140:DI]
Creating newreg=287, assigning class ALL_REGS to slow/invalid mem r287
Creating newreg=288, assigning class ALL_REGS to slow/invalid mem r288
103: r203:SI=r288:SI<<0x1+r196:DI#0
REG_DEAD r196:DI
Inserting slow/invalid mem reload before:
316: r287:DI=[r105:DI*0x8+r140:DI]
317: r288:SI=r287:DI#0
----------------------------------------------------------------------------
The problem is with r287. We rightly give it a broad starting class of
POINTER_AND_FP_REGS (reduced from ALL_REGS by preferred_reload_class).
However, we never make forward progress towards narrowing it down to
a specific choice of class (POINTER_REGS or FP_REGS).
I think in practice we rely on two things to narrow a reload pseudo's
class down to a specific choice:
(1) a restricted class is specified when the pseudo is created
This happens for input address reloads, where the class is taken
from the target's chosen base register class. It also happens
for simple REG reloads, where the class is taken from the chosen
alternative's constraints.
(2) uses of the reload pseudo as a direct input operand
In this case get_reload_reg tries to reuse the existing register
and narrow its class, instead of creating a new reload pseudo.
However, neither occurs here. As described above, r287 rightly
starts out with a wide choice of class, ultimately derived from
ALL_REGS, so we don't get (1). And as the comments in the PR
explain, r287 is never used as an input reload, only the subreg is,
so we don't get (2):
----------------------------------------------------------------------------
Choosing alt 13 in insn 317: (0) r (1) w {*movsi_aarch64}
Creating newreg=291, assigning class FP_REGS to r291
317: r288:SI=r291:SI
Inserting insn reload before:
320: r291:SI=r287:DI#0
----------------------------------------------------------------------------
IMO, in this case we should rely on the reload of r316 to narrow
down the class of r278. Currently we do:
----------------------------------------------------------------------------
Choosing alt 7 in insn 316: (0) r (1) m {*movdi_aarch64}
Creating newreg=289 from oldreg=287, assigning class GENERAL_REGS to r289
316: r289:DI=[r105:DI*0x8+r140:DI]
Inserting insn reload after:
318: r287:DI=r289:DI
---------------------------------------------------
i.e. we create a new pseudo register r289 and give *that* pseudo
GENERAL_REGS instead. This is because get_reload_reg only narrows
down the existing class for OP_IN and OP_INOUT, not OP_OUT.
But if we have a reload pseudo in a reload instruction and have chosen
a specific class for the reload pseudo, I think we should simply install
it for OP_OUT reloads too, if the class is a subset of the existing class.
We will need to pick such a register whatever happens (for r289 in the
example above). And as explained in the PR, doing this actually avoids
an unnecessary move via the FP registers too.
The patch is quite aggressive in that it does this for all reload
pseudos in all reload instructions. I wondered about reusing the
condition for a reload move in in_class_p:
INSN_UID (curr_insn) >= new_insn_uid_start
&& curr_insn_set != NULL
&& ((OBJECT_P (SET_SRC (curr_insn_set))
&& ! CONSTANT_P (SET_SRC (curr_insn_set)))
|| (GET_CODE (SET_SRC (curr_insn_set)) == SUBREG
&& OBJECT_P (SUBREG_REG (SET_SRC (curr_insn_set)))
&& ! CONSTANT_P (SUBREG_REG (SET_SRC (curr_insn_set)))))))
but I can't really justify that on first principles. I think we
should apply the rule consistently until we have a specific reason
for doing otherwise.
gcc/
PR rtl-optimization/96796
* lra-constraints.c (in_class_p): Add a default-false
allow_all_reload_class_changes_p parameter. Do not treat
reload moves specially when the parameter is true.
(get_reload_reg): Try to narrow the class of an existing OP_OUT
reload if we're reloading a reload pseudo in a reload instruction.
gcc/testsuite/
PR rtl-optimization/96796
* gcc.c-torture/compile/pr96796.c: New test.
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index 580da9c3ed6..161b721efb1 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -236,12 +236,17 @@ get_reg_class (int regno)
CL. Use elimination first if REG is a hard register. If REG is a
reload pseudo created by this constraints pass, assume that it will
be allocated a hard register from its allocno class, but allow that
- class to be narrowed to CL if it is currently a superset of CL.
+ class to be narrowed to CL if it is currently a superset of CL and
+ if either:
+
+ - ALLOW_ALL_RELOAD_CLASS_CHANGES_P is true or
+ - the instruction we're processing is not a reload move.
If NEW_CLASS is nonnull, set *NEW_CLASS to the new allocno class of
REGNO (reg), or NO_REGS if no change in its class was needed. */
static bool
-in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class)
+in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class,
+ bool allow_all_reload_class_changes_p = false)
{
enum reg_class rclass, common_class;
machine_mode reg_mode;
@@ -266,7 +271,8 @@ in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class)
typically moves that have many alternatives, and restricting
reload pseudos for one alternative may lead to situations
where other reload pseudos are no longer allocatable. */
- || (INSN_UID (curr_insn) >= new_insn_uid_start
+ || (!allow_all_reload_class_changes_p
+ && INSN_UID (curr_insn) >= new_insn_uid_start
&& curr_insn_set != NULL
&& ((OBJECT_P (SET_SRC (curr_insn_set))
&& ! CONSTANT_P (SET_SRC (curr_insn_set)))
@@ -551,13 +557,12 @@ init_curr_insn_input_reloads (void)
curr_insn_input_reloads_num = 0;
}
-/* Create a new pseudo using MODE, RCLASS, ORIGINAL or reuse already
- created input reload pseudo (only if TYPE is not OP_OUT). Don't
- reuse pseudo if IN_SUBREG_P is true and the reused pseudo should be
- wrapped up in SUBREG. The result pseudo is returned through
- RESULT_REG. Return TRUE if we created a new pseudo, FALSE if we
- reused the already created input reload pseudo. Use TITLE to
- describe new registers for debug purposes. */
+/* Create a new pseudo using MODE, RCLASS, ORIGINAL or reuse an existing
+ reload pseudo. Don't reuse an existing reload pseudo if IN_SUBREG_P
+ is true and the reused pseudo should be wrapped up in a SUBREG.
+ The result pseudo is returned through RESULT_REG. Return TRUE if we
+ created a new pseudo, FALSE if we reused an existing reload pseudo.
+ Use TITLE to describe new registers for debug purposes. */
static bool
get_reload_reg (enum op_type type, machine_mode mode, rtx original,
enum reg_class rclass, bool in_subreg_p,
@@ -616,6 +621,35 @@ get_reload_reg (enum op_type type, machine_mode mode, rtx original,
if (type == OP_OUT)
{
+ /* Output reload registers tend to start out with a conservative
+ choice of register class. Usually this is ALL_REGS, although
+ a target might narrow it (for performance reasons) through
+ targetm.preferred_reload_class. It's therefore quite common
+ for a reload instruction to require a more restrictive class
+ than the class that was originally assigned to the reload register.
+
+ In these situations, it's more efficient to refine the choice
+ of register class rather than create a second reload register.
+ This also helps to avoid cycling for registers that are only
+ used by reload instructions. */
+ if (REG_P (original)
+ && (int) REGNO (original) >= new_regno_start
+ && INSN_UID (curr_insn) >= new_insn_uid_start
+ && in_class_p (original, rclass, &new_class, true))
+ {
+ unsigned int regno = REGNO (original);
+ if (lra_dump_file != NULL)
+ {
+ fprintf (lra_dump_file, " Reuse r%d for output ", regno);
+ dump_value_slim (lra_dump_file, original, 1);
+ }
+ if (new_class != lra_get_allocno_class (regno))
+ lra_change_class (regno, new_class, ", change to", false);
+ if (lra_dump_file != NULL)
+ fprintf (lra_dump_file, "\n");
+ *result_reg = original;
+ return false;
+ }
*result_reg
= lra_create_new_reg_with_unique_value (mode, original, rclass, title);
return true;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr96796.c b/gcc/testsuite/gcc.c-torture/compile/pr96796.c
new file mode 100644
index 00000000000..8808e62fe77
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr96796.c
@@ -0,0 +1,55 @@
+/* { dg-additional-options "-fcommon" } */
+
+struct S0 {
+ signed f0 : 8;
+ unsigned f1;
+ unsigned f4;
+};
+struct S1 {
+ long f3;
+ char f4;
+} g_3_4;
+
+int g_5, func_1_l_32, func_50___trans_tmp_31;
+static struct S0 g_144, g_834, g_1255, g_1261;
+
+int g_273[120] = {};
+int *g_555;
+char **g_979;
+static int g_1092_0;
+static int g_1193;
+int safe_mul_func_int16_t_s_s(int si1, int si2) { return si1 * si2; }
+static struct S0 *func_50();
+int func_1() { func_50(g_3_4, g_5, func_1_l_32, 8, 3); }
+void safe_div_func_int64_t_s_s(int *);
+void safe_mod_func_uint32_t_u_u(struct S0);
+struct S0 *func_50(int p_51, struct S0 p_52, struct S1 p_53, int p_54,
+ int p_55) {
+ int __trans_tmp_30;
+ char __trans_tmp_22;
+ short __trans_tmp_19;
+ long l_985_1;
+ long l_1191[8];
+ safe_div_func_int64_t_s_s(g_273);
+ __builtin_printf((char*)g_1261.f4);
+ safe_mod_func_uint32_t_u_u(g_834);
+ g_144.f0 += 1;
+ for (;;) {
+ struct S1 l_1350 = {&l_1350};
+ for (; p_53.f3; p_53.f3 -= 1)
+ for (; g_1193 <= 2; g_1193 += 1) {
+ __trans_tmp_19 = safe_mul_func_int16_t_s_s(l_1191[l_985_1 + p_53.f3],
+ p_55 % (**g_979 = 10));
+ __trans_tmp_22 = g_1255.f1 * p_53.f4;
+ __trans_tmp_30 = __trans_tmp_19 + __trans_tmp_22;
+ if (__trans_tmp_30)
+ g_1261.f0 = p_51;
+ else {
+ g_1255.f0 = p_53.f3;
+ int *l_1422 = g_834.f0 = g_144.f4 != (*l_1422)++ > 0 < 0 ^ 51;
+ g_555 = ~0;
+ g_1092_0 |= func_50___trans_tmp_31;
+ }
+ }
+ }
+}

View File

@ -1,77 +0,0 @@
commit 6d134ca4b963706f31251f061fc180e517b32546
Author: Martin Sebor <msebor@redhat.com>
Date: Tue Feb 23 14:09:00 2021 -0700
PR c++/99074 - crash in dynamic_cast<>() on null pointer
libstdc++-v3/ChangeLog:
PR c++/99074
* libsupc++/dyncast.cc (__dynamic_cast): Return null when
first argument is null.
gcc/testsuite/ChangeLog:
PR c++/99074
* g++.dg/warn/Wnonnull11.C: New test.
diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull11.C b/gcc/testsuite/g++.dg/warn/Wnonnull11.C
new file mode 100644
index 00000000000..5f1b69d9a41
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wnonnull11.C
@@ -0,0 +1,40 @@
+/* PR c++/99074 - gcc 8 and above is crashing with dynamic_cast<>() on null
+ pointer with optimization level -O1 and above
+ { dg-do run }
+ { dg-options "-O1 -Wall" } */
+
+class Base
+{
+public:
+ virtual ~Base() {}
+ virtual void op() = 0;
+};
+
+class Object: public virtual Base { };
+
+class AbstractBase: public virtual Base
+{
+public:
+ Object* _to_object ()
+ {
+ return dynamic_cast<Object*>(this); // { dg-warning "\\\[-Wnonnull" "" { xfail *-*-* } }
+ }
+};
+
+class MyAbstractClass: public virtual AbstractBase
+{
+public:
+ static MyAbstractClass* _nil () { return 0; }
+};
+
+
+int main ()
+{
+ MyAbstractClass *my_abs_type = MyAbstractClass::_nil ();
+ AbstractBase *abs_base = my_abs_type;
+ Object *obj = abs_base->_to_object ();
+
+ __builtin_printf ("object is: %p\n", obj);
+
+ return 0;
+}
diff --git a/libstdc++-v3/libsupc++/dyncast.cc b/libstdc++-v3/libsupc++/dyncast.cc
index b7d98495ad3..f8f707ee4d4 100644
--- a/libstdc++-v3/libsupc++/dyncast.cc
+++ b/libstdc++-v3/libsupc++/dyncast.cc
@@ -47,6 +47,9 @@ __dynamic_cast (const void *src_ptr, // object started from
const __class_type_info *dst_type, // desired target type
ptrdiff_t src2dst) // how src and dst are related
{
+ if (!src_ptr)
+ /* Handle precondition violations gracefully. */
+ return NULL;
const void *vtable = *static_cast <const void *const *> (src_ptr);
const vtable_prefix *prefix =
adjust_pointer <vtable_prefix> (vtable,

View File

@ -1,47 +0,0 @@
commit 29dad307b5d7cfdb6626c11c8e43ebff941c950b
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Thu Mar 11 16:43:51 2021 +0000
libstdc++: Initialize std::normal_distribution::_M_saved [PR 99536]
This avoids a false positive -Wmaybe-uninitialized warning, by
initializing _M_saved on construction.
libstdc++-v3/ChangeLog:
PR libstdc++/99536
* include/bits/random.h (normal_distribution): Use
default-initializer for _M_saved and _M_saved_available.
(cherry picked from commit 67e397660611990efd98f9e4106c1ee81f6803a4)
diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h
index b36781ed290..3385345d273 100644
--- a/libstdc++-v3/include/bits/random.h
+++ b/libstdc++-v3/include/bits/random.h
@@ -1974,12 +1974,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit
normal_distribution(result_type __mean = result_type(0),
result_type __stddev = result_type(1))
- : _M_param(__mean, __stddev), _M_saved_available(false)
+ : _M_param(__mean, __stddev)
{ }
explicit
normal_distribution(const param_type& __p)
- : _M_param(__p), _M_saved_available(false)
+ : _M_param(__p)
{ }
/**
@@ -2158,8 +2158,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const param_type& __p);
param_type _M_param;
- result_type _M_saved;
- bool _M_saved_available;
+ result_type _M_saved = 0;
+ bool _M_saved_available = false;
};
/**

View File

@ -25,6 +25,8 @@ gcc/testsuite/ChangeLog:
2 files changed, 13 insertions(+), 9 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/abi/lambda-defarg1.C
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 6c111342b97..4399165ee23 100644
--- gcc/cp/mangle.c
+++ gcc/cp/mangle.c
@@ -1628,6 +1628,7 @@ write_literal_operator_name (tree identifier)
@ -52,6 +54,9 @@ gcc/testsuite/ChangeLog:
write_char ('d');
write_compact_number (i - 1);
}
diff --git a/gcc/testsuite/g++.dg/abi/lambda-defarg1.C b/gcc/testsuite/g++.dg/abi/lambda-defarg1.C
new file mode 100644
index 00000000000..8c538581240
--- /dev/null
+++ gcc/testsuite/g++.dg/abi/lambda-defarg1.C
@@ -0,0 +1,11 @@

View File

@ -1,456 +0,0 @@
commit ee3db7c8f844556d35a66b3732bad9f44a086491
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Mon Sep 27 20:44:24 2021 +0100
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 7e5c2073554..2eb1c3f7863 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 b1169428afb..5877d30ba52 100644
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
@@ -140,7 +140,8 @@ namespace __detail
return true;
if (this->_M_atom())
{
- while (this->_M_quantifier());
+ while (this->_M_quantifier())
+ ;
return true;
}
return false;
@@ -410,7 +411,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 +425,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,
@@ -453,27 +446,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))
@@ -482,16 +475,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())
@@ -508,49 +501,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 236ab663fc0..57088f5af83 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
@@ -68,6 +68,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);
@@ -77,7 +87,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)));
@@ -92,7 +101,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)));
}
@@ -157,6 +186,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()
{
@@ -166,6 +225,7 @@ main()
test04();
test05();
test06();
+ test07();
return 0;
}
commit 1851cc4c5f2666dfdec53a2ada57095ffc59e08b
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Mon Dec 13 13:36:33 2021 +0000
libstdc++: Fix non-reserved name in <regex> header
libstdc++-v3/ChangeLog:
* include/bits/regex_compiler.tcc (_Compiler::_M_match_token):
Use reserved name for parameter.
* testsuite/17_intro/names.cc: Check "token".
(cherry picked from commit b0e6a257f1862e217cdf19332ea0f7bad56dcddc)
diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc
index 8af920e5fe9..b1169428afb 100644
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
@@ -586,9 +586,9 @@ namespace __detail
template<typename _TraitsT>
bool
_Compiler<_TraitsT>::
- _M_match_token(_TokenT token)
+ _M_match_token(_TokenT __token)
{
- if (token == _M_scanner._M_get_token())
+ if (__token == _M_scanner._M_get_token())
{
_M_value = _M_scanner._M_get_value();
_M_scanner._M_advance();
diff --git a/libstdc++-v3/testsuite/17_intro/names.cc b/libstdc++-v3/testsuite/17_intro/names.cc
index d758138dfb1..6c06aba7228 100644
--- a/libstdc++-v3/testsuite/17_intro/names.cc
+++ b/libstdc++-v3/testsuite/17_intro/names.cc
@@ -99,6 +99,7 @@
#define z (
#define tmp (
+#define token (
#if __cplusplus < 201103L
#define uses_allocator (
--- a/libstdc++-v3/include/bits/c++config.orig 2022-07-08 15:06:14.083231445 -0400
+++ b/libstdc++-v3/include/bits/c++config 2022-07-08 15:06:41.733247859 -0400
@@ -99,6 +99,12 @@
# define _GLIBCXX_ABI_TAG_CXX11 __attribute ((__abi_tag__ ("cxx11")))
#endif
+// Macro to warn about unused results.
+#if __cplusplus >= 201703L
+# define _GLIBCXX_NODISCARD [[__nodiscard__]]
+#else
+# define _GLIBCXX_NODISCARD
+#endif
#if __cplusplus

View File

@ -1,101 +0,0 @@
The cprop_hardreg pass is built around the assumption that accessing a
register in a narrower mode is the same as accessing the lowpart of
the register. This unfortunately is not true for vector registers on
IBM Z. This caused a miscompile of LLVM with GCC 8.5. The problem
could not be reproduced with upstream GCC unfortunately but we have to
assume that it is latent there. The right fix would require
substantial changes to the cprop pass and is certainly something we
would want for our platform. But since this would not be acceptable
for older GCCs I'll go with what Vladimir proposed in the RedHat BZ
and introduce a hopefully temporary and undocumented target hook to
disable that specific transformation in regcprop.c.
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -10488,6 +10488,18 @@ s390_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
return false;
}
+/* Implement TARGET_NARROW_MODE_REFERS_LOW_PART_P. */
+
+static bool
+s390_narrow_mode_refers_low_part_p (unsigned int regno)
+{
+ if (reg_classes_intersect_p (VEC_REGS, REGNO_REG_CLASS (regno)))
+ return false;
+
+ return true;
+}
+
+
/* Implement TARGET_MODES_TIEABLE_P. */
static bool
@@ -16956,6 +16968,9 @@ s390_case_values_threshold (void)
#undef TARGET_CASE_VALUES_THRESHOLD
#define TARGET_CASE_VALUES_THRESHOLD s390_case_values_threshold
+#undef TARGET_NARROW_MODE_REFERS_LOW_PART_P
+#define TARGET_NARROW_MODE_REFERS_LOW_PART_P s390_narrow_mode_refers_low_part_p
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h"
--- a/gcc/regcprop.c
+++ b/gcc/regcprop.c
@@ -426,7 +426,8 @@ maybe_mode_change (machine_mode orig_mode, machine_mode copy_mode,
if (orig_mode == new_mode)
return gen_raw_REG (new_mode, regno);
- else if (mode_change_ok (orig_mode, new_mode, regno))
+ else if (mode_change_ok (orig_mode, new_mode, regno)
+ && targetm.narrow_mode_refers_low_part_p (copy_regno))
{
int copy_nregs = hard_regno_nregs (copy_regno, copy_mode);
int use_nregs = hard_regno_nregs (copy_regno, new_mode);
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -5446,6 +5446,16 @@ value that the middle-end intended.",
bool, (machine_mode from, machine_mode to, reg_class_t rclass),
hook_bool_mode_mode_reg_class_t_true)
+/* This hook is used to work around a problem in regcprop. Hardcoded
+assumptions currently prevent it from working correctly for targets
+where the low part of a multi-word register doesn't align to accessing
+the register with a narrower mode. */
+DEFHOOK_UNDOC
+(narrow_mode_refers_low_part_p,
+"",
+bool, (unsigned int regno),
+hook_bool_uint_true)
+
/* Change pseudo allocno class calculated by IRA. */
DEFHOOK
(ira_change_pseudo_allocno_class,
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -86,6 +86,7 @@ extern void hook_void_tree (tree);
extern void hook_void_tree_treeptr (tree, tree *);
extern void hook_void_int_int (int, int);
extern void hook_void_gcc_optionsp (struct gcc_options *);
+extern bool hook_bool_uint_true (unsigned int);
extern bool hook_bool_uint_uintp_false (unsigned int, unsigned int *);
extern int hook_int_uint_mode_1 (unsigned int, machine_mode);
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -498,6 +498,14 @@ hook_void_gcc_optionsp (struct gcc_optio
{
}
+/* Generic hook that takes an unsigned int and returns true. */
+
+bool
+hook_bool_uint_true (unsigned int)
+{
+ return true;
+}
+
/* Generic hook that takes an unsigned int, an unsigned int pointer and
returns false. */

View File

@ -1,103 +0,0 @@
diff --git a/gcc/testsuite/g++.dg/torture/phi-1.C b/gcc/testsuite/g++.dg/torture/phi-1.C
new file mode 100644
index 00000000000..69fb3d7ba38
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/phi-1.C
@@ -0,0 +1,28 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "--param early-inlining-insns=14" }
+
+struct Element;
+template <int _Nm> struct __array_traits { typedef Element _Type[_Nm]; };
+template <int _Nm> struct array {
+ typename __array_traits<_Nm>::_Type _M_elems;
+};
+bool logLevel();
+struct LogCapture {
+ void stream();
+};
+struct Element {
+ Element();
+ long data_;
+};
+using ElementArray = array<6>;
+struct ElementManager {
+ ElementManager();
+ ElementArray array_;
+};
+static ElementArray makeArray() {
+ if (logLevel())
+ LogCapture().stream();
+ ElementArray foo;
+ return foo;
+}
+ElementManager::ElementManager() : array_(makeArray()) {}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 84e58e66628..78c0c6a4189 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -2944,35 +2944,6 @@ last_and_only_stmt (basic_block bb)
return NULL;
}
-/* Reinstall those PHI arguments queued in OLD_EDGE to NEW_EDGE. */
-
-static void
-reinstall_phi_args (edge new_edge, edge old_edge)
-{
- edge_var_map *vm;
- int i;
- gphi_iterator phis;
-
- vec<edge_var_map> *v = redirect_edge_var_map_vector (old_edge);
- if (!v)
- return;
-
- for (i = 0, phis = gsi_start_phis (new_edge->dest);
- v->iterate (i, &vm) && !gsi_end_p (phis);
- i++, gsi_next (&phis))
- {
- gphi *phi = phis.phi ();
- tree result = redirect_edge_var_map_result (vm);
- tree arg = redirect_edge_var_map_def (vm);
-
- gcc_assert (result == gimple_phi_result (phi));
-
- add_phi_arg (phi, arg, new_edge, redirect_edge_var_map_location (vm));
- }
-
- redirect_edge_var_map_clear (old_edge);
-}
-
/* Returns the basic block after which the new basic block created
by splitting edge EDGE_IN should be placed. Tries to keep the new block
near its "logical" location. This is of most help to humans looking
@@ -3012,11 +2983,24 @@ gimple_split_edge (edge edge_in)
new_bb = create_empty_bb (after_bb);
new_bb->count = edge_in->count ();
- e = redirect_edge_and_branch (edge_in, new_bb);
- gcc_assert (e == edge_in);
-
+ /* We want to avoid re-allocating PHIs when we first
+ add the fallthru edge from new_bb to dest but we also
+ want to avoid changing PHI argument order when
+ first redirecting edge_in away from dest. The former
+ avoids changing PHI argument order by adding them
+ last and then the redirection swapping it back into
+ place by means of unordered remove.
+ So hack around things by temporarily removing all PHIs
+ from the destination during the edge redirection and then
+ making sure the edges stay in order. */
+ gimple_seq saved_phis = phi_nodes (dest);
+ unsigned old_dest_idx = edge_in->dest_idx;
+ set_phi_nodes (dest, NULL);
new_edge = make_single_succ_edge (new_bb, dest, EDGE_FALLTHRU);
- reinstall_phi_args (new_edge, e);
+ e = redirect_edge_and_branch (edge_in, new_bb);
+ gcc_assert (e == edge_in && new_edge->dest_idx == old_dest_idx);
+ /* set_phi_nodes sets the BB of the PHI nodes, so do it manually here. */
+ dest->il.gimple.phi_nodes = saved_phis;
return new_bb;
}

View File

@ -1,110 +0,0 @@
commit 8b89515caca5149329c0cd20485e69e2d0f879d4
Author: Marek Polacek <polacek@redhat.com>
Date: Wed Dec 7 13:44:38 2022 -0500
strlen: Use D_S_U in maybe_set_strlen_range
This patch fixes #2137448 where the customer uses strlen on a buffer
that was filled by converting the buffer to a struct and copying a string
into a flexible array member of the struct.
This regressed with r262438 in the sense that the strlen was folded to 0.
The strlen=0 result started with
https://gcc.gnu.org/pipermail/gcc-patches/2018-July/501912.html
https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=715fcd73b66c639d9e0e3f3ef9c6ff9d621d7131
which seems like an undesirable change. It was fixed (back to strlen=3) by
https://gcc.gnu.org/legacy-ml/gcc-patches/2019-01/msg00069.html
https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=d4bf69750d31d08068f8242225b8fa06cdf11411
but the changes are not backportable.
Instead, this patch makes maybe_set_strlen_range use DECL_SIZE_UNIT
rather than TYPE_SIZE_UNIT, fixing the regression.
I could never reproduce the problem in C, only C++. C/C++ represent array
type domains differently: C has
char[0:]
but C++
char[0:18446744073709551615]
I'm not sure if that explains it. In any case, I put the new test into
c-c++-common/.
Also, the original test had
printf("strlen = %zu\n", strlen(q->name));
so naturally, for the testsuite, I wanted to convert that into
if (strlen(q->name) != ...)
__builtin_abort ();
but then I could no longer reproduce the problem. After some poking
I realized I want -fno-early-inlining.
Co-authored-by: Jakub Jelinek <jakub@redhat.com>
diff --git a/gcc/testsuite/c-c++-common/torture/strlenopt-1.c b/gcc/testsuite/c-c++-common/torture/strlenopt-1.c
new file mode 100644
index 00000000000..e8c11044119
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strlenopt-1.c
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-fno-early-inlining" } */
+
+#define FORTIFY_SOURCE 2
+
+struct S {
+ char skip;
+ char name[0];
+};
+
+static char static_buf[4];
+
+static void
+print_name_len(void *p)
+{
+ struct S *q = (struct S *) p;
+ if (__builtin_strlen(q->name) != 2)
+ __builtin_abort ();
+}
+
+int
+main(void)
+{
+ // treat static storage as struct
+ struct S *c = (struct S *)static_buf;
+ __builtin_strcpy(c->name, "aa");
+
+ // copy static storage to stack storage
+ char stack_buf[4] = { 0 };
+ __builtin_memcpy(stack_buf, static_buf, 4);
+
+ // static and stack both now contain ( 0, 'a', 'a', 0 }
+
+ // indirectly pass the stack storage to the length function
+ char *s = (char *)stack_buf;
+ print_name_len(s);
+ return 0;
+}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 55e82e7b638..da47046cc2a 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -1200,8 +1200,11 @@ maybe_set_strlen_range (tree lhs, tree src)
|| array_at_struct_end_p (src))
return;
- tree type = TREE_TYPE (src);
- if (tree size = TYPE_SIZE_UNIT (type))
+ src = get_base_address (src);
+ if (!DECL_P (src))
+ return;
+
+ if (tree size = DECL_SIZE_UNIT (src))
if (size && TREE_CODE (size) == INTEGER_CST)
{
wide_int max = wi::to_wide (size);

View File

@ -1,75 +0,0 @@
From 6f989c5c6e5f909996a117bb24ecac936e7526c1 Mon Sep 17 00:00:00 2001
From: Marek Polacek <polacek@redhat.com>
Date: Wed, 14 Jun 2023 17:09:15 -0400
Subject: [PATCH] final: fix for TLSLD references [BZ#2213753]
Patch by Jakub Jelinek.
---
gcc/final.c | 17 +++++++++++++++++
gcc/testsuite/g++.dg/tls/bz2213753.C | 26 ++++++++++++++++++++++++++
2 files changed, 43 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/tls/bz2213753.C
diff --git a/gcc/final.c b/gcc/final.c
index 5a65a8ce07c..c783fbb83d7 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -1691,6 +1691,23 @@ get_some_local_dynamic_name ()
}
}
+ /* If all the TLSLD references from current function were DCEd, try harder and pick
+ name of any TLSLD symbol in current TU. */
+ varpool_node *node;
+ if (!this_is_asm_operands)
+ FOR_EACH_VARIABLE (node)
+ if (DECL_THREAD_LOCAL_P (node->decl)
+ && TREE_STATIC (node->decl)
+ && decl_tls_model (node->decl) == TLS_MODEL_LOCAL_DYNAMIC
+ && DECL_RTL_SET_P (node->decl))
+ {
+ rtx rtl = DECL_RTL (node->decl);
+ if (MEM_P (rtl)
+ && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF
+ && SYMBOL_REF_TLS_MODEL (XEXP (rtl, 0)) == TLS_MODEL_LOCAL_DYNAMIC)
+ return XSTR (XEXP (rtl, 0), 0);
+ }
+
return 0;
}
diff --git a/gcc/testsuite/g++.dg/tls/bz2213753.C b/gcc/testsuite/g++.dg/tls/bz2213753.C
new file mode 100644
index 00000000000..0c4742d8058
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tls/bz2213753.C
@@ -0,0 +1,26 @@
+// RHBZ #2213753
+// { dg-do compile { target c++11 } }
+// { dg-require-effective-target fpic }
+// { dg-require-effective-target shared }
+// { dg-require-effective-target tls }
+// { dg-options "-fPIC -O2" }
+// { dg-add-options tls }
+
+struct A { ~A (); };
+static thread_local int *t;
+int a;
+A::~A () { t = &a; }
+long b;
+
+void *
+foo ()
+{
+ void *c;
+ if (t)
+ {
+ c = operator new (b);
+ return c;
+ }
+ void *d = operator new (b);
+ return d;
+}
--
2.40.1

View File

@ -1,91 +0,0 @@
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. */

View File

@ -1,106 +0,0 @@
commit 1467907e405bc18fb6935b5d432cfa5f936e838d
Author: Andreas Krebbel <krebbel@linux.ibm.com>
Date: Thu Mar 30 13:57:54 2023 +0200
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_tiesi, stack_tiedi): ... this.
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 20424537558..952c708be7a 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -10921,9 +10921,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)
@@ -11035,8 +11033,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)
@@ -11105,10 +11102,14 @@ 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);
+ rtx stack_reg = (frame_pointer_needed
+ ? hard_frame_pointer_rtx
+ : stack_pointer_rtx);
+ if (TARGET_64BIT)
+ emit_insn (gen_stack_tiedi (mem, stack_reg));
+ else
+ emit_insn (gen_stack_tiesi (mem, stack_reg));
}
/* Copy GPRS into FPR save slots. */
@@ -11701,6 +11702,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 7114609b676..f235df3a25d 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -11366,10 +11366,19 @@
; 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_tiesi"
[(set (match_operand:BLK 0 "memory_operand" "+m")
- (unspec:BLK [(match_dup 0)] UNSPEC_TIE))]
+ (unspec:BLK [(match_dup 0)
+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_TIE))]
+ "!TARGET_64BIT"
""
+ [(set_attr "length" "0")])
+
+(define_insn "stack_tiedi"
+ [(set (match_operand:BLK 0 "memory_operand" "+m")
+ (unspec:BLK [(match_dup 0)
+ (match_operand:DI 1 "register_operand" "r")] UNSPEC_TIE))]
+ "TARGET_64BIT"
""
[(set_attr "length" "0")])

View File

@ -1,545 +0,0 @@
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_really_used_regs[i])
- RTX_FRAME_RELATED_P (insn) = 1;
}
else if (!TARGET_PACKED_STACK || call_really_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
-mindirect-branch* or -mfunction-return* options. The sections
consist of an array of 32 bit elements. Each entry holds the offset
from the entry to the patched location.
+
+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\\)" } } */

View File

@ -4,7 +4,7 @@
%global gcc_major 8
# Note, gcc_release must be integer, if you want to add suffixes to
# %%{release}, append them after %%{gcc_release} on Release: line.
%global gcc_release 22
%global gcc_release 3
%global nvptx_tools_gitrev c28050f60193b3b95a18866a96f03334e874e78f
%global nvptx_newlib_gitrev aadc8eb0ec43b7cd0dd2dfb484bae63c8b05ef24
%global _unpackaged_files_terminate_build 0
@ -199,7 +199,7 @@ Requires: libisl.so.15
%endif
%if %{build_libstdcxx_docs}
BuildRequires: doxygen >= 1.7.1
BuildRequires: graphviz, dblatex, texlive-collection-latex, docbook-style-xsl
BuildRequires: graphviz, dblatex, texlive-collection-latex, docbook5-style-xsl
%endif
Requires: cpp = %{version}-%{release}
# Need .eh_frame ld optimizations
@ -279,34 +279,10 @@ Patch18: gcc8-remove-old-demangle.patch
Patch19: gcc8-rh1960701.patch
Patch20: gcc8-pr100797.patch
Patch21: gcc8-rh1981822.patch
Patch22: gcc8-Wbidi-chars.patch
Patch23: gcc8-pr96796.patch
Patch24: gcc8-pch-tweaks.patch
Patch25: gcc8-aarch64-mtune-neoverse-512tvb.patch
Patch26: gcc8-rh2028609.patch
Patch27: gcc8-libgfortran-default-values.patch
Patch28: gcc8-rh2001788.patch
Patch29: gcc8-rh2117838.patch
Patch30: gcc8-rh1668903-1.patch
Patch31: gcc8-rh1668903-2.patch
Patch32: gcc8-rh1668903-3.patch
Patch33: gcc8-harden-1.patch
Patch34: gcc8-harden-2.patch
Patch35: gcc8-harden-3.patch
Patch36: gcc8-harden-4.patch
Patch37: gcc8-pr105502.patch
Patch38: gcc8-pr99536.patch
Patch39: gcc8-libstdc++-make_shared.patch
Patch40: gcc8-rh2137448.patch
Patch41: gcc8-s390x-regarg-1.patch
Patch42: gcc8-s390x-regarg-2.patch
Patch43: gcc8-s390x-regarg-3.patch
Patch44: gcc8-rh2213753.patch
Patch45: gcc8-pr99074.patch
Patch46: gcc8-pr87723.patch
Patch47: gcc8-pr111039.patch
Patch48: gcc8-pr111070.patch
Patch49: gcc8-RHEL-32886.patch
Patch1000: nvptx-tools-no-ptxas.patch
Patch1001: nvptx-tools-build.patch
@ -852,25 +828,6 @@ NVidia PTX. OpenMP and OpenACC programs linked with -fopenmp will
by default add PTX code into the binaries, which can be offloaded
to NVidia PTX capable devices if available.
%package plugin-annobin
Summary: The annobin plugin for gcc, built by the installed version of gcc
Requires: gcc = %{version}-%{release}
# Starting with release 10.01 annobin fixed a bug in its configure scripts
# which prevented them from working with a built but not installed compiler
BuildRequires: annobin >= 10.01
# Starting with release 9.93 annobin-plugin-gcc puts a copy of the sources
# in /usr/src/annobin
# FIXME: Currently the annobin-plugin-gcc subpackage only exists in Fedora.
# For RHEL-9 the annobin package does everything.
# BuildRequires: annobin-plugin-gcc
# Needed in order to be able to decompress the annobin source tarball.
BuildRequires: xz
%description plugin-annobin
This package adds a version of the annobin plugin for gcc. This version
of the plugin is explicitly built by the same version of gcc that is installed
so that there cannot be any synchronization problems.
%prep
%setup -q -n gcc-%{version}-%{DATE} -a 1 -a 2
%patch0 -p0 -b .hack~
@ -902,35 +859,10 @@ so that there cannot be any synchronization problems.
%patch19 -p0 -b .rh1960701~
%patch20 -p0 -b .pr100797~
%patch21 -p0 -b .rh1981822~
%patch22 -p1 -b .bidi~
%patch23 -p1 -b .pr96796~
%patch24 -p1 -b .pch-tweaks~
%patch25 -p1 -b .neoverse~
%patch26 -p1 -b .rh2028609~
%patch27 -p1 -b .libgfortran-default~
%patch28 -p1 -b .rh2001788~
%patch29 -p1 -b .rh2117838~
%patch30 -p0 -b .rh1668903-1~
%patch31 -p0 -b .rh1668903-2~
%patch32 -p0 -b .rh1668903-3~
%patch33 -p1 -b .harden-1~
%patch34 -p1 -b .harden-2~
%patch35 -p1 -b .harden-3~
%patch36 -p1 -b .harden-4~
%patch37 -p1 -b .pr105502~
%patch38 -p1 -b .pr99536~
%patch39 -p1 -b .make_shared~
%patch40 -p1 -b .rh2137448~
%patch41 -p1 -b .s390x-regarg-1~
%patch42 -p1 -b .s390x-regarg-2~
%patch43 -p1 -b .s390x-regarg-3~
%patch44 -p1 -b .rh2213753~
%patch45 -p1 -b .pr99074~
%patch46 -p1 -b .pr87723~
%patch47 -p1 -b .pr111039~
%patch48 -p1 -b .pr111070~
%patch49 -p0 -b .32886~
cd nvptx-tools-%{nvptx_tools_gitrev}
%patch1000 -p1 -b .nvptx-tools-no-ptxas~
@ -1268,82 +1200,6 @@ done)
rm -f rpm.doc/changelogs/gcc/ChangeLog.[1-9]
find rpm.doc -name \*ChangeLog\* | xargs bzip2 -9
# Get the annobin sources. Note these are not added to the rpm as SOURCE4
# because if they were the build phase would try to include them as part of
# gcc itself, and this causes problems. Instead we locate the sources in
# the buildroot. They should have been put there when annobin was installed.
pushd %{_builddir}
%global annobin_source_dir %{_usrsrc}/annobin
if [ -d %{annobin_source_dir} ]
then
# Unpack the sources.
echo "Unpacking annobin sources"
rm -fr annobin-*
tar xvf %{annobin_source_dir}/latest-annobin.tar.xz
# Setting this as a local symbol because using %%global does not appear to work.
annobin_dir=$(find . -maxdepth 1 -type d -name "annobin*")
# Now build the annobin plugin using the just built compiler.
echo "annobin directory = ${annobin_dir}"
cd ${annobin_dir}
# Change the plugin so that it generates "nop" instead of ".nop" instructions.
sed -e "s/\.nop/nop/" -i gcc-plugin/annobin.cc
# Work out where this version of gcc stores its plugins.
%global ANNOBIN_GCC_PLUGIN_DIR %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin
CONFIG_ARGS="--quiet"
CONFIG_ARGS="$CONFIG_ARGS --with-gcc-plugin-dir=%{ANNOBIN_GCC_PLUGIN_DIR}"
CONFIG_ARGS="$CONFIG_ARGS --without-annocheck"
CONFIG_ARGS="$CONFIG_ARGS --without-tests"
CONFIG_ARGS="$CONFIG_ARGS --disable-rpath"
comp_dir="%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/gcc/"
ccompiler="%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/gcc/xgcc -B $comp_dir"
cxxcompiler="%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/gcc/xg++ -B $comp_dir"
comp_flags="%build_cflags"
comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/gcc"
comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/gcc/"
comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/%{gcc_target_platform}/libstdc++-v3/include"
comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/%{gcc_target_platform}/libstdc++-v3/include/%{gcc_target_platform}"
comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/libstdc++-v3/libsupc++"
comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/include"
comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/libcpp/include"
ld_flags="%build_ldflags"
ld_flags="$ld_flags -L%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/libstdc++-v3/.libs"
ld_flags="$ld_flags -L%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/%{gcc_target_platform}/libstdc++-v3/.libs"
ld_flags="$ld_flags -L%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/%{gcc_target_platform}/libstdc++-v3/src/.libs"
ld_flags="$ld_flags -L%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/libstdc++-v3/libsupc++/.libs"
ld_flags="$ld_flags -L%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/%{gcc_target_platform}/libstdc++-v3/libsupc++/.libs"
ld_flags="$ld_flags -L%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/%{gcc_target_platform}/libgcc/.libs"
# libtool works with CFLAGS but ignores LDFLAGS, so we have to combine them.
comp_flags="$comp_flags $ld_flags"
echo "Configuring the annobin plugin"
CC="${ccompiler}" CFLAGS="${comp_flags}" \
CXX="${cxxcompiler}" CXXFLAGS="${comp_flags}" \
LDFLAGS="${ld_flags}" \
./configure ${CONFIG_ARGS} || cat config.log
echo "Building the annobin plugin"
make
echo "Annobin plugin build complete"
else
echo "Unable to locate annobin sources (expected to find: %{annobin_source_dir}/latest-annobin.tar.xz)"
echo "These should be provided by installing the annobin package"
exit 1
fi
popd
%install
rm -rf %{buildroot}
@ -1501,7 +1357,7 @@ mkdir -p %{buildroot}/%{_lib}
mv -f %{buildroot}%{_prefix}/%{_lib}/libgcc_s.so.1 %{buildroot}/%{_lib}/libgcc_s-%{gcc_major}-%{DATE}.so.1
chmod 755 %{buildroot}/%{_lib}/libgcc_s-%{gcc_major}-%{DATE}.so.1
ln -sf libgcc_s-%{gcc_major}-%{DATE}.so.1 %{buildroot}/%{_lib}/libgcc_s.so.1
%ifarch %{ix86} x86_64 ppc ppc64 ppc64p7 ppc64le %{arm} aarch64
%ifarch %{ix86} x86_64 ppc ppc64 ppc64p7 ppc64le %{arm}
rm -f $FULLPATH/libgcc_s.so
echo '/* GNU ld script
Use the shared library, but some functions are only in
@ -2123,20 +1979,6 @@ rm -f %{buildroot}%{mandir}/man3/ffi*
# Help plugins find out nvra.
echo gcc-%{version}-%{release}.%{_arch} > $FULLPATH/rpmver
# Rename the annobin plugin to gcc-annobin.
mkdir -p %{buildroot}%{ANNOBIN_GCC_PLUGIN_DIR}
pushd %{buildroot}%{ANNOBIN_GCC_PLUGIN_DIR}
annobin_dir=$(find %{_builddir} -maxdepth 1 -type d -name "annobin*")
echo "annobin directory = ${annobin_dir}"
cp ${annobin_dir}/gcc-plugin/.libs/annobin.so.0.0.0 gcc-annobin.so.0.0.0
rm -f gcc-annobin.so.0 gcc-annobin.so
ln -s gcc-annobin.so.0.0.0 gcc-annobin.so.0
ln -s gcc-annobin.so.0.0.0 gcc-annobin.so
popd
%check
cd obj-%{gcc_target_platform}
@ -3332,75 +3174,7 @@ fi
%{_prefix}/%{_lib}/libgomp-plugin-nvptx.so.*
%endif
%files plugin-annobin
%{ANNOBIN_GCC_PLUGIN_DIR}/gcc-annobin.so
%{ANNOBIN_GCC_PLUGIN_DIR}/gcc-annobin.so.0
%{ANNOBIN_GCC_PLUGIN_DIR}/gcc-annobin.so.0.0.0
%changelog
* Thu Apr 18 2024 Marek Polacek <polacek@redhat.com> 8.5.0-22
- fix ICE in the vectorizer (RHEL-32886)
* Wed Oct 4 2023 Marek Polacek <polacek@redhat.com> 8.5.0-21
- guard the bit test merging code in if-combine (RHEL-11483)
* Wed Jun 14 2023 Marek Polacek <polacek@redhat.com> 8.5.0-20
- fix for TLSLD references (#2213753)
- fix crash in dynamic_cast<>() on null pointer (PR c++/99074, #2211506)
- adjust a pattern in s390.md (PR target/87723, #2214847)
* Tue Apr 4 2023 Marek Polacek <polacek@redhat.com> 8.5.0-19
- s390x: add support for register arguments preserving (#2168205)
* Tue Dec 6 2022 Marek Polacek <polacek@redhat.com> 8.5.0-18
- fix strlen range with a flexible member array (#2137448)
* Mon Oct 3 2022 Marek Polacek <polacek@redhat.com> 8.5.0-17
- fix deserialization for std::normal_distribution (#2130392,
PR libstdc++/105502)
- initialize std::normal_distribution::_M_saved (PR libstdc++/99536)
- reject std::make_shared<T[]> (PR libstdc++/99006)
* Thu Sep 29 2022 Marek Polacek <polacek@redhat.com> 8.5.0-16
- avoid changing PHIs in GIMPLE split_edge (#2117838)
* Wed Jul 20 2022 Marek Polacek <polacek@redhat.com> 8.5.0-15
- backport straight-line-speculation mitigation (#2108721)
* Fri Jul 8 2022 Jonathan Wakely <jwakely@redhat.com> 8.5.0-14
- backport std::regex check for invalid range (#2001788)
* Wed Apr 20 2022 Marek Polacek <polacek@redhat.com> 8.5.0-13
- require docbook-style-xsl instead of docbook5-style-xsl (#2073888)
- backport Default widths with -fdec-format-defaults patch (#2074614)
* Fri Apr 01 2022 Marek Polacek <polacek@redhat.com> 8.5.0-12
- Fix nop generation in annobin plugin. (#2067150)
* Wed Mar 30 2022 Marek Polacek <polacek@redhat.com> 8.5.0-11
- Add a plugin-annobin subpackage. (#2067150)
* Thu Jan 27 2022 Marek Polacek <polacek@redhat.com> 8.5.0-10
- fix typo in the cprop_hardreg patch (#2028609)
* Mon Jan 24 2022 Marek Polacek <polacek@redhat.com> 8.5.0-9
- apply cprop_hardreg fix for narrow mode != lowpart targets (#2028609)
* Mon Jan 24 2022 Marek Polacek <polacek@redhat.com> 8.5.0-8
- aarch64: Add -mtune=neoverse-512tvb (#1845932)
* Fri Dec 10 2021 Marek Polacek <polacek@redhat.com> 8.5.0-7
- backport PCH tweaks (#2030878)
* Fri Dec 3 2021 Marek Polacek <polacek@redhat.com> 8.5.0-6
- avoid cycling on certain subreg reloads (PR rtl-optimization/96796, #2028798)
* Tue Nov 30 2021 Marek Polacek <polacek@redhat.com> 8.5.0-5
- when linking against libgcc_s, link libgcc.a too (#2022588)
* Thu Nov 18 2021 Marek Polacek <polacek@redhat.com> 8.5.0-4
- add -Wbidi-chars patch (#2008392)
* Tue Jul 13 2021 Marek Polacek <polacek@redhat.com> 8.5.0-3
- fix mangling of lambdas in default args (PR c++/91241, #1981822)
- add a few Provides: bundled